CONOZCÁMONOS Sergio Arbeo Matemático, troll. Programador Ruby y CoffeeScript, entre otros. CodeCantor, ConectaLab Profesor de Rails avanzado en IronHack
PRIMER EJERCICIO 1. Crea dos ficheros desde la terminal: a . t x t y b . t x t . 2. Crea un script en Node que lea los dos ficheros y los imprima en orden inverso al leído. 3. Os interesa el módulo f s y el método r e a d F i l e . 4. Cinco minutillos.
PRIMER EJERCICIO: SOLUCIÓN v a r f s = r e q u i r e ( ' f s ' ) ; f s . r e a d F i l e ( " a . t x t " , " u t f 8 " , f u n c t i o n ( e r r , d a t a ) { i f ( e r r ) t h r o w e r r ; v a r f i r s t F i l e = d a t a ; f s . r e a d F i l e ( " b . t x t " , " u t f 8 " , f u n c t i o n ( e r r , d a t a ) { i f ( e r r ) t h r o w e r r ; v a r s e c o n d F i l e = d a t a ; c o n s o l e . l o g ( s e c o n d F i l e ) ; c o n s o l e . l o g ( f i r s t F i l e ) ; } ) ; } ) ;
PRIMER EJERCICIO: GENERALIZADO Utiliza a s y n c para generalizar fácilmente el ejercicio anterior a tantos ficheros como haga falta. Recomendación del día: a s y n c . m a p .
PRIMER EJERCICIO: GENERALIZADO v a r f s = r e q u i r e ( ' f s ' ) ; v a r a s y n c = r e q u i r e ( ' a s y n c ' ) ; v a r r f = f u n c t i o n ( f i l e n a m e , c b ) { r e t u r n f s . r e a d F i l e ( f i l e n a m e , " u t f 8 " , c b ) ; } ; a s y n c . m a p ( [ " a . t x t " , " b . t x t " , " c . t x t " ] , r f , f u n c t i o n ( e r r , d a t a ) { i f ( e r r ) { t h r o w e r r ; } f o r ( v a r i = d a t a . l e n g t h - 1 ; i > = 0 ; i - - ) { c o n s o l e . l o g ( d a t a [ i ] ) ; } } ) ;
META Poder escribir código, manteniendo la asincronicidad, lo más parecido a: v a r f s = r e q u i r e ( ' f s ' ) v a r a F i l e = f s . r e a d F i l e ( ' a . t x t ' , ' u t f 8 ' ) ; v a r b F i l e = f s . r e a d F i l e ( ' b . t x t ' , ' u t f 8 ' ) ; c o n s o l e . l o g ( b F i l e ) ; c o n s o l e . l o g ( a F i l e ) ;
GENERADORES: DEFINICIÓN A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values. Generators, also known as semicoroutines, are a special case of (and weaker than) coroutines. Wikipedia
CORRUTINA: DEFINICIÓN Components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations. Wikipedia
GENERADOR: EJEMPLO v a r q u e e n = f u n c t i o n * ( ) { y i e l d " J o h n D e a c o n " ; y i e l d " F r e d d i e M e r c u r y " ; y i e l d " B r i a n M a y " ; y i e l d " R o g e r T a y l o r " ; } ; f o r ( v a r p o f q u e e n ( ) ) { c o n s o l e . l o g ( p ) ; } Usad n o d e - - h a r m o n y
ARGUMENTOS EN GENERADORES: EJERCICIO Escribid un generador que, dado otro generador y una función, devuelva un generador m a p . 1. Cread un generador que devuelva una lista de valores (ej. números del 1 al 5). El último elemento tiene que devolverse con return. 2. Usad n e x t ( ) para obtener el siguiente valor de un generador. 3. Cread un generador m a p . 4. Imprimid el resultado usándolo como iterador.
ARGUMENTOS EN GENERADORES: SOLUCIÓN v a r m a p G e n = f u n c t i o n * ( g e n , f n ) { i f ( i s G e n e r a t o r ( g e n ) ) { g e n = g e n ( ) ; } v a r c u r r e n t = g e n . n e x t ( ) ; w h i l e ( ! c u r r e n t . d o n e ) { y i e l d f n ( c u r r e n t . v a l u e ) ; c u r r e n t = g e n . n e x t ( ) ; } r e t u r n c u r r e n t . v a l u e ; } ; v a r i s G e n e r a t o r = f u n c t i o n ( o b j ) { r e t u r n o b j & & o b j . c o n s t r u c t o r & & ' G e n e r a t o r F u n c t i o n ' = = o b j . c o n s t r u c t o r . n a m e ; }
ARGUMENTOS EN GENERADORES: CONCLUSIONES n e x t devuelve un objeto con dos claves: v a l u e y d o n e y i e l d para la ejecución del generador, dejándola suspendida y i e l d hace que la respuesta de n e x t tenga d o n e : f a l s e r e t u r n hace que la respuesta de n e x t tenga d o n e : t r u e ¿Qué pasa con el último valor de un generador al usarlo como iterador?
YIELD ES UNA PALABRA CLAVE v a r a r r g e n = f u n c t i o n * ( a r r ) { a r r . f o r E a c h ( f u n c t i o n ( e l ) { y i e l d e l ; } ) ; } ; v a r s e q = a r r g e n ( [ 1 , 2 , 3 ] ) ; c o n s o l e . l o g ( s e q . n e x t ( ) ) ; c o n s o l e . l o g ( s e q . n e x t ( ) ) ; c o n s o l e . l o g ( s e q . n e x t ( ) ) ;
YIELD ES UNA PALABRA CLAVE g e n - t 3 c h f e s t / y i e l d _ e x a m p l e . j s : 3 y i e l d e l ; ^ ^ S y n t a x E r r o r : U n e x p e c t e d i d e n t i f i e r a t e x p o r t s . r u n I n T h i s C o n t e x t ( v m . j s : 6 9 : 1 6 ) a t M o d u l e . _ c o m p i l e ( m o d u l e . j s : 4 3 2 : 2 5 ) a t O b j e c t . M o d u l e . _ e x t e n s i o n s . . j s ( m o d u l e . j s : 4 6 7 : 1 0 ) a t M o d u l e . l o a d ( m o d u l e . j s : 3 4 9 : 3 2 ) a t F u n c t i o n . M o d u l e . _ l o a d ( m o d u l e . j s : 3 0 5 : 1 2 ) a t F u n c t i o n . M o d u l e . r u n M a i n ( m o d u l e . j s : 4 9 0 : 1 0 ) a t s t a r t u p ( n o d e . j s : 1 2 3 : 1 6 ) a t n o d e . j s : 1 1 2 8 : 3
MÚLTIPLES PUNTOS DE ENTRADA 1. Cread una sucesión de Pell: 1. El primer elemento es 0. 2. El segundo elemento es 1. 3. El elemento n es 2 veces el (n-1)-ésimo más el (n-2)-ésimo. 4. El elemento inicial es 1. 2. ¿Qué ocurre si pasáis un parámetro a n e x t ? 3. Modificad el generador del primer punto para que se pueda resetear.
MÚLTIPLES PUNTOS DE ENTRADA v a r p e l l = f u n c t i o n * ( ) { v a r a = 0 , b = 1 , c = 0 ; w h i l e ( t r u e ) { y i e l d b ; c = a ; a = b ; b + = c + b ; } } ;
MÚLTIPLES PUNTOS DE ENTRADA SOLUCIÓN 3 v a r p e l l = f u n c t i o n * ( ) { v a r a = 0 , b = 1 , c = 0 ; w h i l e ( t r u e ) { v a r r e s u l t = y i e l d b ; i f ( r e s u l t ) { a = 0 ; b = 1 ; } e l s e { c = a ; a = b ; b + = c + b ; } } } ;
EJECUCIÓN DE PELL v a r p e l l = f u n c t i o n * ( ) { v a r a = 0 , b = 1 , c = 0 ; w h i l e ( t r u e ) { v a r r e s u l t = y i e l d b ; i f ( r e s u l t ) { a = 0 ; b = 1 ; } e l s e { c = a ; a = b ; b + = c + b ; } } } ; v a r s e q = p e l l ( ) ; c o n s o l e . l o g ( s e q . n e x t ( ) ) ; / / 1 c o n s o l e . l o g ( s e q . n e x t ( ) ) ; / / 2 c o n s o l e . l o g ( s e q . n e x t ( ) ) ; / / 5 c o n s o l e . l o g ( s e q . n e x t ( t r u e ) ) ; / / ?
ÚLTIMO EJERCICIO Crea una función e a c h C o n s 2 que, dado un generador, devuelva dos valores consecutivos. Por ejemplo: El generador original devuelve 1, 2, 3, 4, 5, 6... e a c h C o n s 2 devolverá [ 1 , 2 ] ,[ 2 , 3 ] ,[ 3 , 4 ] ,...
ÚLTIMO EJERCICIO v a r e a c h C o n s 2 = f u n c t i o n * ( g e n ) { i f ( i s G e n e r a t o r ( g e n ) ) { g e n = g e n ( ) ; } v a r a = g e n . n e x t ( ) , b = g e n . n e x t ( ) ; w h i l e ( ! b . d o n e ) { y i e l d [ a . v a l u e , b . v a l u e ] ; a = b ; b = g e n . n e x t ( ) ; } ; } ;
ÚLTIMO EJERCICIO v a r s q r t 2 = m a p G e n ( e a c h C o n s 2 ( p e l l ) , f u n c t i o n ( a r r ) { r e t u r n ( a r r [ 0 ] + a r r [ 1 ] ) / a r r [ 1 ] ; } ) ;
CONTINUACIÓN A continuation is a program frozen in action: a single functional object containing the state of a computation. When the object is evaluated, the stored computation is restarted where it left off. , Paul Graham On Lisp
IDEA La idea es utilizar un generador como una continuación. Para ello necesitaremos una función a la que llamaremos c u o r e que nos permitirá escribir código como el siguiente: c u o r e ( f u n c t i o n * ( ) { v a r f i r s t F i l e = y i e l d r e a d F i l e ( ' a . t x t ' ) ; v a r s e c o n d F i l e = y i e l d r e a d F i l e ( ' b . t x t ' ) ; c o n s o l e . l o g ( s e c o n d F i l e ) ; c o n s o l e . l o g ( f i r s t F i l e ) ; } ) ( ) ;
THUNKS Denominaremos thunk a una función que devuelve otra función cuyo único argumento es un callback. Escribid un thunk de f s . r e a d F i l e . Debe: 1. Admitir un único argumento, el nombre de archivo. 2. Devolver una función que admita como argumento un callback. 3. La función del retorno, al ser llamada con un callback, deberá llamar a f s . r e a d F i l e con el nombre de archivo pasado, ' u t f 8 ' y el callback.
THUNKS v a r f s = r e q u i r e ( ' f s ' ) ; v a r r e a d F i l e = f u n c t i o n ( f i l e n a m e ) { r e t u r n f u n c t i o n ( c b ) { f s . r e a d F i l e ( f i l e n a m e , ' u t f 8 ' , c b ) ; } ; } ;
CUORE SEMPLICE v a r c u o r e = f u n c t i o n ( g e n ) { r e t u r n f u n c t i o n ( ) { g e n = g e n ( ) ; g e n . n e x t ( ) . v a l u e ( f u n c t i o n ( e r r , d a t a ) { g e n . n e x t ( d a t a ) . v a l u e ( f u n c t i o n ( e r r , d a t a ) { g e n . n e x t ( d a t a ) ; } ) ; } ) ; } ; } ;
CUORE SEMPLICE v a r r f = r e a d F i l e ; c u o r e ( f u n c t i o n * ( ) { v a r f i r s t F i l e = y i e l d r f ( ' a . t x t ' ) ; v a r s e c o n d F i l e = y i e l d r f ( ' b . t x t ' ) ; c o n s o l e . l o g ( s e c o n d F i l e ) ; c o n s o l e . l o g ( f i r s t F i l e ) ; } ) ( ) ;
CO Escrito por TJ Holowaychuk Acepta más tipos desde el yield: 1. Promesas 2. Array 3. Objetos 4. Generadores 5. Funciones generadoras Existen wrappers para ciertos módulos para que funcionen con c o Para todo lo demás, thunkify.
CO: EJEMPLO v a r f s = r e q u i r e ( ' c o - f s ' ) ; v a r c o = r e q u i r e ( ' c o ' ) ; c o ( f u n c t i o n * ( ) { v a r f i r s t F i l e = y i e l d f s . r e a d F i l e ( ' a . t x t ' , ' u t f 8 ' ) ; v a r s e c o n d F i l e = y i e l d f s . r e a d F i l e ( ' b . t x t ' , ' u t f 8 ' ) ; c o n s o l e . l o g ( s e c o n d F i l e ) ; c o n s o l e . l o g ( f i r s t F i l e ) ; } ) ( ) ;
KOA: UN EJEMPLO v a r k o a = r e q u i r e ( ' k o a ' ) ; v a r a p p = k o a ( ) ; a p p . u s e ( f u n c t i o n * ( n e x t ) { c o n s o l e . l o g ( ' A n t e s ' ) ; y i e l d n e x t ; c o n s o l e . l o g ( ' D e s p u é s ' ) ; } ) ; a p p . u s e ( f u n c t i o n * ( ) { t h i s . b o d y = " M i m a m á m e m i m a " ; } ) ; a p p . l i s t e n ( 4 2 4 2 ) ;
KOA EJERCICIO Utiliza t h i s . c o o k i e s . g e t ( n a m e ) y t h i s . c o o k i e s . s e t ( n a m e , v a l u e ) para añadir un texto a la respuesta.
KOA EJERCICIO SOLUCIÓN a p p . u s e ( f u n c t i o n * ( n e x t ) { y i e l d n e x t ; v a r b a c k = t h i s . c o o k i e s . g e t ( ' m a j o ' ) ; i f ( b a c k ) { t h i s . b o d y + = " \ n G r a c i a s p o r v o l v e r . " } t h i s . c o o k i e s . s e t ( ' m a j o ' , t r u e ) } ) ;