0% encontró este documento útil (0 votos)
592 vistas108 páginas

Programacion Funcional JavaScript PDF

Este documento presenta una introducción a la programación funcional en JavaScript. Explica que la programación funcional persigue especificaciones declarativas y objetivos como la inmutabilidad y la transparencia referencial. También cubre principios de diseño funcional como la composicionalidad y variedades funcionales como arquitecturas dirigidas por flujos de datos. El documento analiza estas técnicas funcionales y cómo aplicarlas usando JavaScript.

Cargado por

figo13
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
592 vistas108 páginas

Programacion Funcional JavaScript PDF

Este documento presenta una introducción a la programación funcional en JavaScript. Explica que la programación funcional persigue especificaciones declarativas y objetivos como la inmutabilidad y la transparencia referencial. También cubre principios de diseño funcional como la composicionalidad y variedades funcionales como arquitecturas dirigidas por flujos de datos. El documento analiza estas técnicas funcionales y cómo aplicarlas usando JavaScript.

Cargado por

figo13
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 108

Programación

 Funcional    
en  JavaScript  
Técnicas,  Patrones  y  Arquitecturas  Funcionales  

Javier  Vélez  Reyes  


 @javiervelezreye  
[email protected]  

Octubre  2014  
Programación  Funcional  en  JavaScript  
Presentación  

I.  ¿Quién  Soy?  
  Licenciado   en   informá2ca   por   la   Universidad   Politécnica   de  
Madrid   (UPM)   desde   el   año   2001   y   doctor   en   informá2ca   por   la  
Universidad   Nacional   de   Educación   a   Distancia   (UNED)   desde   el  
año  2009,  Javier  es  inves2gador  y  está  especializado  en  el  diseño  
y   análisis   de   la   colaboración.   Esta   labor   la   compagina   con  
ac2vidades  de  evangelización,  consultoría,  mentoring  y  formación  
especializada  para  empresas  dentro  del  sector  IT.  Inquieto,  ávido  
lector  y  seguidor  cercano  de  las  innovaciones  en  tecnología.  

[email protected]  
II.  ¿A  Qué  Me  Dedico?  
@javiervelezreye  
  Desarrollado  Front/Back  
linkedin.com/in/javiervelezreyes  
Evangelización  Web  
gplus.to/javiervelezreyes   Arquitectura  SoVware  
Formación  &  Consultoría  IT  
jvelez77  
E-­‐learning  
javiervelezreyes   Diseño  de  Sistemas  de  Colaboración  
youtube.com/user/javiervelezreyes  
Learning  Analy2cs  
Gamificación  Colabora2va  
 

2     @javiervelezreye  
Javier  Vélez  Reyes  
 @javiervelezreye  

1  
[email protected]  

Programación  Funcional  en  JavaScript  


Introducción  

§  Introducción  

Introducción  
§  Obje2vos  de  la  Programación  Funcional  
§  Principios  de  Diseño  Funcional  
§  Dimensiones  y  Planos  de  Ac2vidad  
Programación  Funcional  en  JavaScript  
Introducción  

I.  Introducción  
La  programación  funcional  es  un  viejo  conocido  dentro  del  mundo  del  desarrollo.  No  obstante,  
en   los   úl2mos   años   está   cogiendo   tracción   debido,   entre   otros   factores,   a   la   emergencia   de  
arquitecturas   reac2vas,   al   uso   de   esquemas   funcionales   en   el   marco   de   Big   Data   y   al   creciente  
soporte   que   se   le   da   desde   diversas   plataformas   vigentes   de   desarrollo.   JavaScript   ha   sido  
siempre   un   lenguaje   con   fuerte   tendencia   al   diseño   funcional.   En   este   texto   revisaremos   sus  
obje2vos   y   principios   y   discu2remos   los   mecanismos,   técnicas   y   patrones   empleados  
actualmente  para  construir  arquitecturas  funcionales  haciendo  uso  de  JavaScript.        

Programación   Programación  
Funcional   Orientada  a  Objetos  
Arquitecturas  
centradas  en  la   Variantes   Puntos  de  Extensión  
transformación   funcionales   Polimórfica   Arquitecturas  
centradas  en  la  
abstracciones  
Inmutabilidad   Transparencia   SusEtuEvidad  
Referencial   Liskoviana  
ComposiEvidad   Encapsulación  de  
estado  
Arquitecturas   Arquitecturas  
dirigidas  por  flujos  de   dirigidas  por  flujos  de  
datos   control  

4     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

II.  ObjeQvos  de  la  Programación  Funcional  


A.  Especificación  DeclaraQva  
La   programación   funcional   persigue   diseñar   especificaciones   de   comportamiento   abstracto  
que  se  centren  en  la  descripción  de  las  caracterís2cas  de  un  problema  más  que  en  una  forma  
par2cular   de   resolverlo.   De   acuerdo   a   esto,   se   en2ende   que   la   responsabilidad   de   encontrar  
una   solución   para   el   problema   descansa   no   tanto   en   manos   del   programador   sino   en   la  
arquitectura  funcional  subyacente  que  toma  en  cuenta  dicha  especificación.  

Funcional   La   descripción   fluida   del   esElo   function total (type) {


funcional   permite   entender   fácil-­‐
Qué   mente  la  especificación  
var result = 0;
for (var idx = 0; idx < basket.length; idx++) {
var item = basket[idx];
function total (type) { if (basket[idx].type === type)
return basket.filter (function (e) { result += item.amount * item.price;
return e.type === type; }
}).reduce (function (ac, e) { return result; Aunque   operaEvamente   es   equivalente,  
return ac + e.amount * e.price; }
el   esElo   imperaEvo   es   más   confuso   y  
}, 0); resulta  más  diRcil  de  entender    
}

var basket = [
Cómo  
{ product: 'oranges', type:'food', amount: 2, price:15 }, Objetos  
{ product: 'bleach' , type:'home', amount: 2, price:15 },
{ product: 'pears' , type:'food', amount: 3, price:45 },
{ product: 'apples' , type:'food', amount: 3, price:25 },
{ product: 'gloves' , type:'home', amount: 1, price:10 }
];

5     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

II.  ObjeQvos  de  la  Programación  Funcional  


B.  Abstracción  Funcional  
La   programación   funcional   persigue   alcanzar   una   especificación   de   alto   nivel   que   capture  
esquemas   algorítmicos   de   aplicación   transversal.   Como   veremos   a   con2nuación,   así   se  
fomenta   la   reu2lización   y   la   adaptación   idiomá2ca.   Esto   se   consigue   con   arquitecturas  
centradas  en  la  variabilidad  funcional  y  contrasta  ortogonalmente  con  la  orientación  a  objetos.    
Funcional   var vehicles = [new Car(), new Truck(), ...];
Abstracción  Funcional   var garage = function (vehicles) {
for (v in vehicles)
v   vehicles[v].test();
body   };
garage(vehicles);
paint  
vehicles   V1   V2   V3  
var phases = [
function body (v) {...},
function paint (v) {...} En   OOP   los   algoritmos  
]; Car   Truck   se   distribuyen   entre  
var test = function (phases) { objetos   con   implemen-­‐
function (vehicle) { Bike   taciones  variantes  
return phases.reduce(function (ac, fn) {
return fn(ac);
}, vehicle); Abstracción  de  Qpos  
}
En  FP  la  función  es  la  unidad  de  abstracción  ya  que   Objetos  
};
permite   definir   esquemas   algorítmicos   que  
dependen  de  funciones  pasadas  como  parámetros  
6     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

II.  ObjeQvos  de  la  Programación  Funcional  


C.  ReuQlización  Funcional  
Como   consecuencia   de   la   capacidad   de   abstracción   en   la   especificación   declara2va,   la  
programación   funcional   alcanza   cotas   elevadas   en   la   reu2lización   de   funciones.   Este   nivel   de  
reu2lización  algorítmica  no  se  consigue  en  otros  paradigmas  como  en  la  orientación  a  objetos.  
var get = function (collection) {
return function (filter, reducer, base) {
return collection
.filter(filter)
.reduce(reducer, base);
El   esquema   algorítmico   se   reuEliza  
};
sobre  disEntas  estructuras  de  datos  y  
};
con  disEntas  aplicaciones  funcionales  

var users = [ var basket = [


{ name: 'jvelez', sex: 'M', age: 35 }, { product: 'oranges', type: 'F', price:15 },
{ name: 'eperez', sex: 'F', age: 15 }, { product: 'bleach' , type: 'H', price:15 },
{ name: 'jlopez', sex: 'M', age: 26 } { product: 'pears' , type: 'F', price:45 },
]; ];
var adult = function (u) { return u.age > 18; }; var food = function (p) { return p.type === 'F'; };
var name = function (ac, u) { var total = function (ac, p) {
ac.push(u.name); return ac + p.price;
return ac; };
}; get(basket)(food, total, 0);
get(users)(adult, name, []);

7     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

II.  ObjeQvos  de  la  Programación  Funcional  


D.  Adaptación  Funcional  
Una   de   las   virtudes   de   la   programación   funcional   es   la   capacidad   de   poder   transformar   la  
morfología  de  las  funciones  para  adaptarlas  a  cada  escenario  de  aplicación  real.  En  términos  
concretos   esto   significa   poder   cambiar   la   signatura   de   la   función   y   en   especial   la   forma   en   que  
se   proporcionan   los   parámetros   de   entrada   y   resultados   de   salida.   Veremos   que   existen  
mecanismos  técnicas  y  patrones  para  ar2cular  este  proceso.  

function greater (x, y) { reverse   function greater (x, y) {


return x > y; return y > x;
} }
Se   invierte   el   orden   de   aplica-­‐
ción   de   los   parámetros   de   Se  transforma  la  evaluación  de  
forma  transparente   curry   la   función   para   que   pueda   ser    
evaluada  por  fases  

(function greater (x) { parQal   function greater (x) {


function (y) { function (y) {
return y > x; return y > x;
} }
})(18) Se   configura   parcialmente   la   }
función   para   obtener   el  
predicado  de  adulto  

8     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

II.  ObjeQvos  de  la  Programación  Funcional  


E.  Dinamicidad  Funcional  
La   programación   funcional   permite   diseñar   funciones   que   sean   capaces   de   construir  
abstracciones   funcionales   de   forma   dinámica   en   respuesta   a   la   demanda   del   contexto   de  
aplicación.   Como   veremos,   este   obje2vo   se   apoya   en   mecanismos   de   abstracción   y   también  
abunda  en  la  adaptación  funcional  que  acabamos  de  describir.  
La   función   greater   es   una   factoría   Proveedor  
funcional   que   define   comporta-­‐
mientos  dinamicamente  
function greater (x) {
return function (y) {
return y > x;
}
var isOld = greater(65) var isYoung = greater(25)
}

var isAdult = greater(25)


Clientes  
isOld('jlopez') isAdult('jlopez') isYoung('jlopez')

Se   demanda   un   predicado   Se   demanda   un   predicado   Se   demanda   un   predicado  


funcional   que   discrimine   a   los   funcional   que   discrimine   a   los   funcional   que   discrimine   a   los  
jubilados   adultos   jóvenes  

9     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

III.  Principios  de  Diseño  Funcional  


A.  Principio  de  Transparencia  Referencial  
El   principio   de   transparencia   referencial   predica   que   en   toda   especificación   funcional   correcta,  
cualquier  función  debe  poder  subs2tuirse  en  cualquier  ámbito  de  aplicación  por  su  expresión  
funcional   sin   que   ello   afecte   al   resultado   obtenido.   La   interpretación   de   este   principio   de  
diseño  2ene  tres  lecturas  complementarias.  
var old = greater(65)
Funciones  Puras  

Dado   que   el   predicado   greater   sólo   depende   de  


sus   parámetros   de   entrada   x   e   y,   se   trata   de   una  
función   pura.   Por   ello,   manEene   la   transparencia  
referencial  permiEendo  su  susEtución  sin  impacto  
en  la  semánEca  del  contexto  de  aplicación   var old = (function greater (x) {
function (y) {
return y > x;
}
})(65);

Estado
Se   dice   que   una   función   es   pura   –   recuerda   al   es2lo   de  
comportamiento   matemá2co   –   si   su   valor   de   retorno   sólo  
f   depende   de   los   parámetros   de   entrada   y   no   del   estado  
ambiental   (variables   globales,   variables   retenidas   en   ámbito  
léxico,  operaciones  de  E/S,  etc.).  

10     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

III.  Principios  de  Diseño  Funcional  


A.  Principio  de  Transparencia  Referencial  
El   principio   de   transparencia   referencial   predica   que   en   toda   especificación   funcional   correcta,  
cualquier  función  debe  poder  subs2tuirse  en  cualquier  ámbito  de  aplicación  por  su  expresión  
funcional   sin   que   ello   afecte   al   resultado   obtenido.   La   interpretación   de   este   principio   de  
diseño  2ene  tres  lecturas  complementarias.  
Comportamiento  Idempotente   EsQlo  Orientado  a  Objetos  
La   pila   manEene   el   estado  
EsQlo  Funcional   interno  y  las  operaciones  push  y   function Stack () {
pop  no  resultan  idempotentes   var items = [];
function Stack () { return {
return { stack: [] }; push: function (e) {
} items.push(e);
function push (s, e) {
El   estado   se   manEene   externa-­‐ },
return {
mente  y  se  pasa  como  parámetro   pop: function () {
stack: s.stack.concat(e), return items.pop();
top: e a   cada   operación   con   lo   que   el  
}
}; comportamiento  es  idempotente   };
} }
function pop (s) {
var stack = [].concat(s.stack);
var e = stack.pop(); Se   dice   que   una   función   es   idempotente   si   siempre   devuelve   el  
return { mismo   resultado   para   los   mismos   parámetros   de   entrada.   En  
stack: stack,
top: e nuestro  ejemplo  debería  verificarse  esta  igualdad:  
};
} pop + pop === 2 * pop

11     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

III.  Principios  de  Diseño  Funcional  


A.  Principio  de  Transparencia  Referencial  
El   principio   de   transparencia   referencial   predica   que   en   toda   especificación   funcional   correcta,  
cualquier  función  debe  poder  subs2tuirse  en  cualquier  ámbito  de  aplicación  por  su  expresión  
funcional   sin   que   ello   afecte   al   resultado   obtenido.   La   interpretación   de   este   principio   de  
diseño  2ene  tres  lecturas  complementarias.  
AgnosQcismo  de  Estado  
Fronteras  Arquitectónicas  
Cada   abstracción   en   el   ámbito   arquitec-­‐
Entrada clean   tónico   es   una   función   pura   que   hace  
depender   su   salida   exclusivamente   de  
words   sus  parámetros  de  entrada  
La   entrada   acumula   toda   la  
información   ambiental   en  
forma  de  estado   count   Salida

Dentro   de   la   arquitectura   el   estado   es  


Todo   problema   de   aplicación   real   se   caracteriza   por   un   estado   acarreado   como   parámetro   a   lo   largo  
intrínseco.  El  agnos2cismo  de  estado  no  niega  esta  realidad.  En  su  lugar,   de  la  cadena  de  transformación    
el   principio   debe   interpretarse   como   que   dentro   de   las   fronteras   del  
sistema   el   comportamiento   funcional   sólo   puede   depender   de   los  
parámetros  explícitamente  definidos  en  cada  función.  

12     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

III.  Principios  de  Diseño  Funcional  


B.  Principio  de  Inmutabilidad  de  Datos  
En   el   modelo   de   programación   impera2va,   la   opera2va   de   computo   se   en2ende   como   un  
proceso   secuencial   y   paula2no   de   transformación   del   estado   mantenido   por   la   arquitectura  
hardware   de   la   máquina.   En   programación   funcional   –   y   en   virtud   de   la   transparencia  
referencial   –   las   funciones   no   dependen   del   estado   ambiental.   De   ello   se   colige   que   el  
concepto  de  variable  entendido  como  deposito  actualizable  de  información  no  existe.  
ImperaQvo   P.  Funcional  
var x = 1 x@(0) = 1
... ...
x = x + 1 x@(t+1) = x@(t) + 1

En   programación   imperaEva   las   variables   se   La  programación  funcional  pone  estrés  en  que  los  cambios  
enEenden   como   depósitos   de   información   en   en   los   datos   de   un   programa   deben   manifestarse   como  
memoria  que  pueden  actualizarse  durante  el  Eempo   funciones  sobre  la  dimensión  Eempo.  Esto  significa  que  el  
de   vida   del   programa.   La   dimensión   Eempo   queda   concepto  de  variables  como  deposito  de  información  y  las  
oculta  y  esto  dificulta  el  razonamiento   operaciones   de   actualización   sobre   ellas   no   están  
permiEdas  
function push (s, e) { EsQlo  ImperaQvo  
return s.push(e); Se  modifica  s  
En   términos   prác2cos   la   aplicación   se   este   }
principio   se   traduce   en   que   las   funciones   nunca  
deben   actualizar   los   parámetros   de   entrada   sino   function push(s, e) { EsQlo  Funcional  
generar  a  par2r  de  ellos  resultados  de  salida   return s.concat(e); No  se  modifica  s  
}

13     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

III.  Principios  de  Diseño  Funcional  


C.  Principio  de  Computación  Centrada  en  Colecciones  
A   diferencia   de   lo   que   ocurre   en   otros   paradigmas   como   en   orientación   a   objetos   donde   los  
datos   se   organizan   en   forma   de   grafos   relacionales,   en   programación   funcional   éstos   deben  
modelarse  como  colecciones  –  arrays  o  diccionarios  en  JavaScript  –  para  que  se  les  pueda  sacar  
pleno   par2do1.   Se   dice   que   el   modelo   de   computación   de   la   programación   funcional   está  
centrado  en  colecciones.  
Set   Binary  Tree   Heap  
Un   conjunto   se   modela   como   Un   array   se   aplana   como   una   Una   cola   con   prioridad   es   un  
un   array   o   un   diccionario   de   colección   anidada   de   arrays   de   diccionario   de   arrays   o   un   array  
booleanos   3   posiciones,   árbol   izquierdo,   de  arrays  
nodo,  árbol  derecho  
[true, {1: [a, c], 1 a c
false, 1 1 2: [b, c, d],
true, [ 3: [f]} 2 b d e
3
true] 4 [ 2 5 3 f
[[],3,[]], [
Bag   2, 3 4 6 7 [a, c],
[[],4,[]]], [b, c, d],
Una   bolsa   se   modela   como   un  
1, [f]
un  diccionario  de  contadores   [[[],6,[]], ]
5,
{a: 2, [[],7,[]]] …   1   Los  
b: 3, aa ] diccionarios   son   una   aproximación   de  
bb representación   aceptable   en   tanto   que  
c: 1} c pueden  procesarse  como  colecciones  de  pares  
clave-­‐valor  

14     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

III.  Principios  de  Diseño  Funcional  


D.  Principio  de  Diseño  Dirigido  por  Capas  
La  construcción  de  arquitecturas  funcionales  sigue  un  proceso  de  diseño  dirigido  por  capas  o  
niveles   de   especificación.   Desde   las   abstracciones   más   generales   encontradas   en   librerías  
funcionales  se  construye  un  nivel  idiomá2co  que  propone  un  esquema  abstracto  de  solución  
para  el  problema  propuesto  y  sólo  entonces  se  concreta  en  el  dominio  par2cular  del  problema.    
Nivel  de  Librería  
map reduce filter ...
Se   uElizan   funciones   generales  
con  un  alto  nivel  de  abstracción  
var get = function (collection) {
return function (filter, reducer, base) {
return collection Nivel  IdiomáQco  
.filter(filter)
Nivel  de  Abstracción  

.reduce(reducer, base); Se   crea   un   esquema   funcional  


}; que   resuelve   la   familia   de  
}; problemas   al   que   pertenece   el  
ReuQlización  Transversal  a  Dominio   problema  planteado  

var users = [{ name: 'jlopez', sex: 'M', age: 26 } ...]; Nivel  de  Dominio  
var male = function (u) { return u.age > 18; };
var name = function (ac, u) { Se   contextualiza   el   esquema  
ac.push(u.name); anterior   dentro   del   dominio   de  
return ac; aplicación   concretando   con  
}; datos  y  funciones  específicas  
get(users)(male, name, []);

15     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

IV.  Caracterización  de  la  Programación  Funcional  


A.  Ejes  Dimensionales  
A   lo   largo   de   esta   introducción   hemos   presentado   el   paradigma   de   programación   funcional  
centrándonos   en   sus   obje2vos   y   principios   fundacionales.   Nos   resta   por   describir   los  
mecanismos  esenciales  en  los  que  se  apoya.  No  obstante,  dado  que  el  soporte  a  los  mismos  
está  fuertemente  condicionado  por  el  lenguaje  estos  aspectos  serán  cubiertos  en  el  siguiente  
capítulo.    
ObjeQvos  
¿Por  qué?   Dec Capítulo  2  
Los   objeEvos   describen   las   caracterísEcas  

}
Abs
diferenciales  de  la  programación  funcional   ¿Con  qué?  
y   jusEfican   sus   procesos   de   desarrollo   en   Reut Los   mecanismos   conforman   las  
relación  a  otros  paradigmas   herramientas   del   lenguaje   para  
Adap arEcular  los  desarrollos  funcionales  
}

Capítulo  1   Dina

Enc

Inm

Par

Com
Abs

Tran Mecanismos  
Inmut
¿Cómo?  
Capas
Los  principios  de  diseño  ofrecen  líneas   }
Principios   maestras   que   dirigen   los   procesos   de   Capítulo  1  
desarrollo  funcional  

16     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Introducción  

IV.  Caracterización  de  la  Programación  Funcional  


B.  Planos  de  AcQvidad  
El   recorrido   de   este   texto   avanza   describiendo   cada   uno   de   los   tres   planos   de   ac2vidad   que  
caracterizan   la   programación   funcional.   En   el   capítulo   3   abordaremos   las   técnicas   de  
programación   esenciales   del   paradigma.   El   capítulo   4   profundiza   en   los   patrones   de   diseño  
funcionales.  Y  el  capítulo  5  presenta  las  principales  arquitecturas  en  programación  funcional.  
ObjeQvos   Programadores  
Arquitecturas  Funcionales   Plano  Tecnológico   Capítulo  3  
Los   esElos   arquitectónicos   propor-­‐

}
cionan   restricciones   estructurales   Abs
que   determinan   formas   canónicas   Técnicas  de  Programación  
de   abordar   familias   específicas   de   Reut Las   técnicas   indican   cómo   aplicar   los  
problemas   mecanismos   del   lenguaje   en   el  
Adap
proceso  de  programación  funcional  
}

Capítulo  5   Arquitectos   Dina

Enc

Inm

Par

Com
Abs

Tran Mecanismos   Capítulo  4  

}
Inmut
o nes   Patrones  de  Diseño  
Capas Patr
El   diseño   establece   formas   canónicas  
Principios   de   aplicabilidad   probada   para   dar  
respuesta  a  problemas  recurrentes    
Diseñadores  

17     @javiervelezreye  
Javier  Vélez  Reyes  
 @javiervelezreye  

2  
[email protected]  

Programación  Funcional  en  JavaScript  


JavaScript    
como  Lenguaje  

JavaScript  como  Lenguaje  Funcional  


Funcional  

§  Definición  Funcional  por  Casos  


§  Definición  por  Recursión  
§  Expresiones  Funcionales  de  Invocación  Inmediata  IIFE  
§  Definición  en  Orden  Superior  
§  Clausuras  &  Retención  de  Variables  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

I.  Introducción  
Como  ya  hemos  comentado,  los  procesos  de  programación  funcional  consisten  esencialmente  
en   la   definición   de   una   colección   de   declaraciones   funcionales   que   puedan   adaptarse   a  
dis2ntos   niveles   de   abstracción   y   aplicarse   conjugadamente   para   resolver   problemas   de   forma  
declara2va.   Para   ar2cular   estas   tareas   de   definición   el   paradigma   funcional   ofrece   una  
colección  de  mecanismos  esenciales  que  revisamos  en  este  capítulo.  
Nivel  IdiomáQco  
App   App   App  
Las   deficiencias   que   por   su  
concepción   presenta   el   lenguaje  
Nivel  de  Lenguaje   Patrones  PF   se   deben   suplir   a   este   nivel   por  
aplicación   de   técnicas   y   patrones  
El   nivel   de   lenguaje   está   formado   Técnicas  PF   de   diseño   que   revisaremos   en  

Sobrecarga  Funcional  

Definición  por  Patrones  


por   la   colección   de   mecanismos   próximos  capítulos  
de  programación  que  proporciona  
JS  Funcional    
el  lenguaje  de  forma  naEva  

Orden  Superior    
recursividad  

Expresiones  IIFE  
Definición  por  casos  

Retención    Variables  
Clausuras  

19     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


A.  Definición  Funcional  por  Casos  
La   forma   más   sencilla   de   definir   una   función   es   diseñando   explícitamente   la   colección   de  
valores  de  retorno  que  debe  devolver  para  cada  posible  parámetro  de  entrada.  Aunque  este  
mecanismo   parece   poco   flexible   aisladamente,   cuando   se   conjuga   con   otras   formas   de  
definición  resulta  de  aplicación  frecuente.    
Enumeración  Explícita  de  casos  
function f (parámetros) { La   definición   por   casos   se   expresa  
Única  Expresión   return caso-1 ? resultado-1 : declarando   explícitamente   el   valor   que  
caso-2 ? resultado-2 : debe   devolver   la   función   para   cada  
El   uso   anidado   del   operador  
resultado-defecto;
condicional   permite   expresar   los   posible   valor   de   los   parámetros   de  
}
pares   caso-­‐resultado   como   una   entrada  
única  expresión  de  retorno  

function comparator(x) { function even(n) {


return x > 0 ? 1 : return n % 2;
x === 0 ? 0 : }
-1 ;
}

Se   uEliza   el   operador   condicional   La   definición   mediante   una   única  


anidado   para   definir   cada   caso   expresión   es   el   escenario   más  
funcional   sencillo  de  definición  por  casos  

20     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


B.  Definición  por  Recursión  
La  definición  de  funciones  por  recursión  consiste  en  la  invocación  de  la  propia  función  como  
parte   del   proceso   de   definición.   El   esquema   de   definición   recursivo   se   apoya   en   el   mecanismo  
anterior   para   dis2nguir   entre   casos   base   –   aquéllos   que   devuelven   un   resultado   final   –   de  
aquéllos  casos  recursivos  –  donde  el  valor  de  retorno  vuelve  a  invocar  a  la  propia  función.      

function f (parámetros) {
return caso-base-1 ? resultado-base-1 :
caso-base-2 ? resultado-base-2 :
Casos  base   caso-recursivo-1 ? resultado-recursivo-1 : Casos  recursivos  
caso-recursivo-2 ? resultado-recursivo-2 :
Los   casos   base   son   el   final   del   Los   casos   recursivos   se  
resultado-defecto ;
proceso  recursivo  y  se  suponen   } diseñan   invocando   a   la  
soluciones   inmediatas   a   propia   función   sobre  
problemas  sencillos     valores   de   parámetros  
que   convergen   a   los  
casos  base    

I.  Regla  de  cobertura   II.  Regla  de  convergencia   III.  Regla  de  autodefinición  
Asegúrese   de   que   todos   los   casos   Asegúrese   de   que   cada   resultado   Para   diseñar   cada   caso   recursivo  
base  del  problema  han  sido  incluidos   recursivo   converge   a   alguno   de   los   asuma  que  la  función  por  definir  está  
explícitamente   en   la   definición   de   la   casos  base   y a   d e fi n i d a   p a r a   v a l o r e s   d e  
función   parámetros  más  próximos  a  los  casos  
base    
21     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


B.  Definición  por  Recursión  
En  función  de  cómo  se  expresan  los  casos  recursivos  de  una  función  podemos  dis2nguir  entre  
dos   2pos   de   situaciones.   En   la   recursión   directa,   los   casos   recursivos   de   la   función   se   expresan  
en   términos   de   llamadas   a   ella   misma.   En   la   recursión   indirecta,   la   función   invoca   a   otra  
función  que  recurre  sobre  la  primera.  

Recursión  Directa   factorial(4) Los   casos   recursivos   convergen  


= 4 * factorial(3) hacia   los   casos   base   reduciendo   el  
function factorial (n) { = 4 * 3 * factorial(2) tamaño   del   problema   en   una  
return n === 0 ? 1 : = 4 * 3 * 2 * factorial(1)
= 4 * 3 * 2 * 1 * factorial(0)
unidad  a  cada  paso  
n * factorial(n - 1);
} = 4 * 3 * 2 * 1 * 1
= 24

Recursión  Indirecta  

even(4) function even (n) {


= !odd(3) return n === 0 ? true :
La  convergencia  hacia  los  casos  base   = !!even(2) !odd(n-1);
va   incluyendo   un   operador   de   = !!!odd(1) }
negación   que   se   resuelven   al   llegar   = !!!!even(0) function odd (n) {
= !!!!true return n === 0 ? false :
al  caso  base  
= true !even(n-1);
}

22     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


B.  Definición  por  Recursión  
Dado   que   la   programación   funcional   no   dispone   de   estructuras   de   control   de   flujo,   la   única  
forma   de   resolver   problemas   que   requieren   un   computo   itera2vo   es   expresarlas   a   par2r   de  
una  formulación  recursiva.  Aunque  puede  resultar  en  principio  más  complejo,  la  expresividad  
funcional   aumenta   con   este   2po   de   expresiones.   Además   hay   problemas   que   2enen   una  
resolución  inherentemente  recursiva.  
Problema  de  las  Torres  de  Hanoi  
Mover  discos  de  uno  en  uno  para  dejarlos  en  la   function hanoi (n, origen, aux, destino) {
misma   posición   de   A   en   C   usando   B   como   if (n === 1) mover(origen, destino);
else {
auxiliar.   Los   discos   por   encima   de   uno   dado   hanoi(n-1, origen, destino, aux);
deben  ser  siempre  de  menor  tamaño  que  éste.   mover(origen, destino);
hanoi(n-1, aux, origen, destino);
n-1 n-1 }
}
function mover (origen, destino) {
A   B   C   destino.push (origen.pop());
3
}
1 var A = [4, 3, 2, 1], B = [], C = []
hanoi(A, B, C);

23     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


C.  Expresiones  Funcionales  e  Invocación  Inmediata  
No  en  pocas  ocasiones  la  necesidad  de  definir  una  función  se  restringe  a  un  solo  uso  que  se  
realiza   a   con2nuación   de   su   definición.   Si   encerramos   una   definición   de   función   entre  
paréntesis   y   aplicamos   a   la   expresión   resultante   el   operador   de   invocación   –   los   parámetros  
actuales   a   su   vez   entre   parentesis   y   separados   por   comas   –   obtenemos   una   expresión  
funcional  de  invocación  inmediata  IIFE.  

(function f (parámetros-formales) {
Expresión  Funcional   Invocación  Inmediata  
La   definición   funcional   se   encierra  
<<cuerpo de declaración funcional>> La   expresión   funcional   se   invoca  
entre   paréntesis   para   converErla   en   directamente   por   aplicación   de   los  
})(parámetros-actuales); parámetros  actuales  
una  expresión  evaluable  

var cfg = (function config(user) { Un   cpico   ejemplo   de   IIFE   se   da   cuando  


// getting config from DB se  pretenden  realizar  cálculos  complejos  
return {...} o  tareas  que  se  efectuarán  una  sola  vez  
})('jvelez'); a  lo  largo  del  código    

La   ventaja   de   este   Epo   de   construcciones  


es   que   la   función   se   libera   de   la   memoria  
tras  su  ejecución  

24     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


D.  Definición  en  Orden  Superior  
En  JavaScript  las  funciones  son  ciudadanos  de  primer  orden.  Esto  quiere  decir  que  a  todos  los  
efectos   no   existe   ningún   2po   de   diferencia   entre   una   función   y   cualquier   valor   de   otro   2po  
primi2vo.   Esto   permite   a   una   función   recibir   otras   funciones   como   parámetros   o   devolver  
funciones  como  retorno.  Este  mecanismo  se  le  conoce  con  el  nombre  de  orden  superior.    

Funciones  como  Parámetros  a  Otras  Funciones  


var greater = function (x, y) {...};
El   paso   de   funciones   como   parámetros   a   una   función   var less = function (x, y) {...};
var even = function (x) {...};
permite   que   el   comportamiento   de   ésta   sea   adaptada   por  
medio  de  la  inyección  de  código  variante  en  cada  invocación.   [1, 4, 3, 2].sort(greater);
Esta   aproximación   contrasta   con   la   programación   por   2pos   [1, 4, 3, 2].sort(less);
variantes  propia  de  la  orientación  a  objetos.   [1, 4, 3, 2].filter(even);

function once (fn) { Funciones  como  Retorno  de  Otras  Funciones  


var called = false;
return function () { Las  funciones  son  capaces  de  generar  dinámicamente  
if (!called) { funciones   que   devuelven   como   resultado.   Esto   es   de  
called = true;
return fn.apply(this, arguments); especial   interés   cuando   la   función   devuelta   es   el  
} resultado   de   transformar   una   función   recibida   como  
} argumento.   Este   proceso   jus2fica   el   nombre   de   orden  
}
superior  ya  que  se  opera  con  funciones  genéricas.  

25     @javiervelezreye  
Programación  Funcional  en  JavaScript  
JavaScript  como  Lenguaje  Funcional  

II.  Mecanismos  de  Programación  Funcional  


E.  Clausuras    &  Retención  de  Variables  
Las   funciones   que,   por   medio   de   los   mecanismos   de   orden   superior,   devuelven   funciones  
como  resultado  se  pueden  expresar  en  términos  de  variables  locales  o  parámetros  presentes  
en  el  entorno  funcional  donde  se  definen.  La  retención  de  variables  es  el  mecanismo  mediante  
el   cual   dichas   variables   y   parámetros   son   mantenidos   durante   todo   el   2empo   de   vida   de   la  
función  de  retorno.  Este  2po  de  funciones  se  denominan  clausuras.  
Variables  Retenidas  
function Logger(cls) { Al   extraer   una   función   fuera   de   su   ámbito  
var pre = 'Logger'; léxico   de   definición   se   manEene   el   contexto  
var post = '...'; de  variables  y  parámetros  que  dicha  función  
return function (message) { uEliza.    
console.log ('%s[%s] - [%s]%s',
pre, cls, message, post);
} pre post cls
}
function (message) {...}
var log = Logger('My Script');
Log('starting');
log(1234);
log('end'); Clausura  
Las   clausuras   son   un   mecanismos   de  
construcción  funcional  que  captura  de  forma  
permanente  un  estado  de  configuración  que  
condiciona  su  comportamiento    

26     @javiervelezreye  
Javier  Vélez  Reyes  
 @javiervelezreye  

3  
[email protected]  

Programación  Funcional  en  JavaScript  


Técnicas  de  
Programación  

Técnicas  de  Programación  Funcional    


Funcional  

§  Abstracción  
§  Encapsulación  
§  Inmersión  por  Recursión  y  Acumulación  
§  Evaluación  Parcial  
§  Composición  Funcional  &  Composición  Monádica  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

I.  Introducción  
A   par2r   de   los   mecanismos   que   ofrece   JavaScript   como   lenguaje   de   programación   se   puede  
escribir   soVware   bien   centrado   en   el   paradigma   funcional.   No   obstante,   para   ello   es   necesario  
conocer  una  colección  de  técnicas  básicas  que  describen  formas  canónicas  de  hacer  frente  a  
problemas   recurrentes.   A   lo   largo   de   este   capítulo   haremos   una   revisión   de   las   técnicas   más  
relevantes.  

Abstracción   Encapsulación   Inmersión  


     
Las  técnicas  de  abstracción  permiten   En  funcional  la  encapsulación  de  estado   Las  técnicas  de  inmersión  son  una  con-­‐
definir  especificaciones  funcionales  con   es  un  mal  a  veces  necesario  y  en   jugación  de  abstracción,  encapsulación  
diferentes  grados  de  generalidad  y   muchas  ocasiones  puede  reemplazarse   y  recursividad  para  obtener  control  de  
reu2lización  transversal   por  encapsulación  de  comportamiento   flujo  dirigido  por  datos  

Evaluación  Parcial   Composición  Funcional   Transformación  Monádica  


     
La  evaluación  parcial  permite    evaluar   La  composición  funcional  permite   La  transformación  monádica  persigue  
una  función  en  varias  fases  reduciendo   ar2cular  procesos  de  secuenciamiento   adaptar  funciones  para  conver2rlas  en  
paula2namente  el  número  de  variables   de  funciones  definidas  como   transformaciones  puras  que  soporten  
libres   expresiones  analí2cas   procesos  de  composición  

Inversión  de  Control  


 
La  inversión  de  control  permite  
permutar  entre  las  arquitecturas  
funcionales  centradas  en  los  datos  y  las  
centradas  en  las  transformaciones  

28     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


A.  Técnicas  de  Abstracción  
Una   de   las   técnica   de   programación   funcional   más   comúnmente   u2lizadas,   en   alineamiento  
con  los  principios  de  diseño  presentados  anteriormente,  es  la  abstracción  funcional.  Las  tareas  
de  abstracción  deben  entenderse  como  un  proceso  de  transformación  en  el  que  la  definición  
de  una  función  se  reexpresa  en  términos  más  generales  para  dar  cobertura  a  un  abanico  más  
amplio  de  escenarios  de  aplicación.  Podemos  dis2nguir  tres  dimensiones  de  abstracción.      

add   addAll  
Suma   convencional   de   dos   nú-­‐ Abstracción  en  
Suma   todos   los   parámetros   de  
meros   pasados   como   para-­‐ Anchura  
la   función   independientemente  
metros   de  la  aridad  
add(x, y) addAll(x, y, z, …)

Abstracción  en  
Alcance  

reduceFrom   addFrom  
Abstracción  en  
Combina   mediante   la   función   c   Comportamiento   Suma   todos   los   parámetros   de  
todos   los   parámetros   a   parEr   la  función  a  parEr  de  aquél  que  
de  uno  dado  en  posición  p     ocupa  una  posición  p  
reduceFrom(p, c)(x, y, …) add(p)(x, y, z, …)

29     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


B.  Técnicas  de  Encapsulación  
Mediante  el  uso  de  clausuras  y  la  retención  de  variables  es  posible  capturar,  durante  la  fase  de  
diseño  o  ejecución,  cierta  información  que  resulta  de  u2lidad  para  adaptar  el  comportamiento  
de   la   función   a   lo   largo   del   2empo.   Es   posible   dis2nguir   entre   encapsulación   de   estado   y   de  
comportamiento.      
Encapsulación  de  Estado.  Pila  Undo  
Retención  de  Estado  
function Stack () {
Las   variables   que   capturan   el   estado   quedan  
var items = [];
var history = []; retenidas   dentro   de   la   clausura   lo   que  
return { permite   arEcular   modelos   de   programación  
push: function (e) { funcional  que  evolucionan  con  el  Eempo  
history.push([].concat(items));
items.push(e);
items   history  
},
pop: function () { 3 1 2 3
history.push([].concat(items)); undo  
return items.pop(); 2 1 2
},
1 1
undo: function () {
if (history.length > 0)
items = history.pop(); Dependencia  de  Estado  
} Ojo!   Las   funciones   que   dependen   del   estado   son   en  
}; realidad  una  mala  prácEca  de  programación  de  acuerdo  
} a  los  principios  de  diseño  del  paradigma    

30     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


B.  Técnicas  de  Encapsulación  
Mediante  el  uso  de  clausuras  y  la  retención  de  variables  es  posible  capturar,  durante  la  fase  de  
diseño  o  ejecución,  cierta  información  que  resulta  de  u2lidad  para  adaptar  el  comportamiento  
de   la   función   a   lo   largo   del   2empo.   Es   posible   dis2nguir   entre   encapsulación   de   estado   y   de  
comportamiento.      
Encapsulación  de  Comportamiento.  Pila  Undo  
function Stack () {
Retención  de  Comportamiento   var items = [];
En  este  caso  la  variable  de  histórico  captura   var history = [];
la   colección   de   operaciones   inversas   que   return {
permiten   deshacer   las   transacciones   según   push: function push (e) {
history.push(function(){items.pop()});
han  ido  sucediendo    
items.push(e);
},
items   history   pop: function pop () {
3 pop   pop   pop   var e = items.pop();
undo   history.push(function(){items.push(e);});
2 pop   pop   return e;
},
1 pop   undo: function undo() {
if (history.length > 0)
Operaciones  Inversas   history.pop()(),
Dentro   de   cada   operación,   se   registran   en   el   }
};
histórico   las   operaciones   inversas   para   luego  
}
invocarlas  desde  la  operación  deshacer  

31     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


B.  Técnicas  de  Encapsulación  
Mediante  el  uso  de  clausuras  y  la  retención  de  variables  es  posible  capturar,  durante  la  fase  de  
diseño  o  ejecución,  cierta  información  que  resulta  de  u2lidad  para  adaptar  el  comportamiento  
de   la   función   a   lo   largo   del   2empo.   Es   posible   dis2nguir   entre   encapsulación   de   estado   y   de  
comportamiento.      
Encapsulación  de  Comportamiento.  Bus   receive   receive('add', +)  

function Bus () { El   consumidor   se  


var fns = {}; r e g i s t r a   e n   l o s  
return { eventos  de  interés  
receive: function (e, fn) {
event   fn   3+2  
fns[e] = fn;
},
add   x  +  y  
send: function (e, ctx) {
return fns[e].apply(null, ctx);
} sub   x  -­‐  y  
};
} bus  
var bus = Bus(); send('add', [3,2])  
bus.receive('add', function (x,y) {return x+y;});
bus.receive('sub', function (x,y) {return x-y;}); send  
bus.send('add', [3,2]);
bus.send('sub', [7,3]);
El   productor   emite   con   la  
operación  send  un  evento  
a  los  receptores  

32     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


C.  Diseño  por  Inmersión  
Dado   que   la   programación   funcional   no   soporta   los   esquemas   itera2vos   propios   de   la  
programación  impera2va,  es  preciso  orientar  los  cálculos  a  la  recurrencia  apoyándose  para  ello  
en  parámetros  auxiliares.  Las  técnicas  de  inmersión  conjugan  encapsulación  y  abstracción  con  
el  uso  de  parámetros  auxiliares.  Podemos  dis2nguir  diferentes  2pos  de  inmersión.  
I.  Inmersión  por  Recorrido  
function find (v, e) { aux([1,2,3], 0) =
var aux = function (v, e, p) { 1 + aux([1,2,3], 1) =
return (p > v.length) ? -1 : 1 + 2 + aux ([1,2,3], 2) =
(v[p] === e) ? p : 1 + 2 + 3 = 6  
aux(v, e, p + 1);
}; La   técnica   se   apoya   es   una  
return aux(v, e, 0); 1 2 3
abstracción   que   queda  
}
sumergida  dentro  de  la  más  

p >  
específica  por  encapsulación  
La  inmersión  de  recorrido  exEende  la  
función   introduciendo   un   nuevo  
function addAll (v) {
parámetro  cuyo  propósito  es  llevar  la  
return (function aux(v, p) {
cuenta   del   punto   hasta   el   que   se   ha   if (p === v.length-1) return v[p];
avanzado  en  el  vector.       else return v[p] + aux (v, p+1);
}) (v, 0);
}

33     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


C.  Diseño  por  Inmersión  
Dado   que   la   programación   funcional   no   soporta   los   esquemas   itera2vos   propios   de   la  
programación  impera2va,  es  preciso  orientar  los  cálculos  a  la  recurrencia  apoyándose  para  ello  
en  parámetros  auxiliares.  Las  técnicas  de  inmersión  conjugan  encapsulación  y  abstracción  con  
el  uso  de  parámetros  auxiliares.  Podemos  dis2nguir  diferentes  2pos  de  inmersión.  
II.  Inmersión  por  Acumulación   aux([1,2,3], 0, 0) =
aux([1,2,3], 1, 1) =
function even (v) { aux ([1,2,3], 2, 3) =
return (function aux(v, p, ac){ aux ([1,2,3], 3, 6) =
if (p === v.length) return ac; 6  
else {
if (v[p] % 2 === 0) ac.push(v[p]); Tail  Recursion  
return aux(v, p+1, ac); La   acumulación   se   aplica  
} 1 2 3
aquí   para   obtener   recursi-­‐
})(v, 0, []);
vidad   final   buscando   la  

p,ac >  
}
eficiencia  en  memoria  

Reducción   function addAll (v) {


Se   uEliza   la   técnica   de   acumulación   return (function aux(v, p, ac) {
para   consolidad   un   vector   formado   if (p === v.length) return ac;
por   el   subconjunto   de   los   elementos   else return aux (v, p+1, v[p]+ac);
pares  del  vector   })(v, 0, 0);
}

34     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


D.  Evaluación  Parcial    
El   uso   de   clausuras   permite   transformar   una   función   para   que   pueda   evaluarse   de   manera  
parcial   resolviendo   sólo   algunos   de   sus   parámetros.   El   resultado   es   una   nueva   función   con  
menos  grados  de  libertad  donde  los  parametros  ya  evaluados  se  fijan  a  un  valor  concreto  y  el  
resto  quedan  como  variables  libres.    
La   dimensión   espacial   vincula  
I.  Dimensiones  Contractuales   convencionalmente   valores   actuales  
En   la   dimensión   temporal   a  parámetros  
A   diferencia   de   lo   que   ocurre   en   otros   cada   fase   conduce   a   una  
paradigmas,   el   diseño   funcional   de   etapa   de   resolución   parcial  
abstracciones  2ene  dos  dimensiones  de   de  parámetros   function color(rr) {
definición,   la   dimensión   espacial   y   la   return function (gg) {
dimensión  temporal.     return function (bb) {
return [rr, gg, bb] ;
};
bb Desde   la   fase   1   a   la   fase   2   se  
};
resuelve   el   parámetro   rr   y  
}
quedan   dos   dimensiones   libres  
gg II.  Reducción  Dimensional  
de  movimiento  (gg,  bb)    
rr
bb Cada   fase   de   aplicación   temporal   de  
parámetros   conduce   a   una   reducción  
rr = cc dimensional  en  el  espacio  del  problema.    

gg color('cc')('a3')('45')

35     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


D.  Evaluación  Parcial    
El   uso   de   la   evaluación   parcial   permite   que  el   programador   vaya   resolviendo  de  forma  faseada  
la   evaluación   de   una   función   a   medida   que   va   disponiendo   de   los   argumentos   actuales  
necesarios.  En  estos  casos,  el  diseño  de  la  función  debe  cuidarse  para  garan2zar  que  el  orden  
en  el  que  se  demandan  los  parámetros  a  lo  largo  del  2empo  corresponde  con  el  esperado  en  el  
contexto  previsto  de  uso.  

Ejemplo.  Evaluación  por  Fases  


Se   arEcula   un   proceso   de   construcción   por  
function schema (scheme) { fases  que  permite  inyectar  las  partes  de  una  
var uri = { scheme : scheme }; Uri.  Este  esquema  recuerda  al  patrón  Builder  
return function (host) { de  OOP  pero  usando  únicamente  funciones  
uri.host = host;
return function (port) {
uri.port = port;
return function (path) { Aunque   la   aplicación   de   este  
uri.path = path; esquema   induce   un   estricto    
return function () { orden   en   la   resolución   para-­‐
return uri; métrica   permite   resolver   por  
}; var host = schema('http');
fases  el  proceso  construcEvo  a  
}; var port = host('foo.com');
}; var path = port(80); medida   que   se   dispone   de   los  
}; var uri = path('index.html'); datos    
} uri();

36     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


D.  Evaluación  Parcial    
Otro   escenario   protolpico   del   uso   de   la   evaluación   parcial   se   da   en   la   comunicación   entre  
funciones  proveedoras  y  clientes.  El  proveedor  resuelve  parcialmente  una  función  reduciendo  
así   el   número   de   dimensiones   y   la   entrega   en   respuesta   a   la   demanda   de   un   cliente   que  
resolverá   el   resto   de   dimensiones   con   argumentos   actuales   en   sucesivas   invocaciones.   En   este  
caso,   el   diseño   funcional   debe   fasearse   teniendo   en   cuenta   la   intervención   primera   del  
proveedor  y  posterior  del  cliente.   Proveedor  
Transferencia  Proveedor  -­‐  Consumidor   RuleEngine(ctx)  
RuleEngine  
function RuleEngine (ctx) {
return function eval(rule) {
return function () { rE  
var args = [].slice.call(arguments); ctx
if (rule.trigger.apply(ctx, args)) Cliente  
return rule.action.apply(ctx, args); function eval(rule) {}
};
}; La   función   obtenida   del   proveedor  
} permite   al   cliente   evaluar   reglas   que  
var rE = RuleEngine({age: 18, login: false}); se  apoyan  en  las  variables  retenidas    

rE ({ trigger: function (age) { return age > this.age; },


El  proveedor  resuelve  parcialmente   action: function () { return this.login = true; } })(19);
una   función   eval   y   la   entrega   como   rE ({ trigger: function () { return this.login; },
resultado  a  la  función  cliente   action: function () { return 'Bienvenido!'; } })();

37     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


E.  Composición  Funcional  
Dado   que   en   programación   funcional   las   abstracciones   son   meras   transformaciones   que   no  
pueden  ar2cular  un  algoritmo  secuencial,  es  frecuente  modelar  el  secuenciamiento  en  base  a  
la   composición.   De   esta   manera,   el   valor   de   retorno   de   una   función   sirve   de   entrada   para   la  
función  subsiguiente.  
La   organización   composiEva   de   funciones  
function clean (s){ return s.trim(); } conduce   a   arquitecturas   centradas   en   las  
function words (s){ return s.split(' '); } transformaciones   que   los   datos   atraviesan   en  
function count (s){ return s.length; } cascada  

count(
words( s clean  
clean('La FP en JS Mola!!!')
)
); words  

count   5
La  cascada  de  composición  funcional  se  recorre  en  senEdo  inverso  
al  natural.  Los  datos  comienzan  por  la  función  más  interna  (clean)  
y  atraviesan  la  cadena  de  composición  ascendentemente  hasta  la  
cima  (count).  En  el  capítulo  siguiente  estudiaremos  patrones  que  
conducen  a  una  lectura  descendente  más  natural  

38     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


E.  Composición  Funcional  
En   ocasiones   la   forma   en   la   que   se   definen   las   abstracciones   funcionales   no   es   compa2ble   con  
los   procesos   de   composición.   Para   poder   ar2cular   adecuadamente   dichos   procesos   debemos  
tener  en  cuenta  dos  reglas  de  transformación  funcional  que  puede  ser  necesario  aplicar  para  
conseguir  funciones  composi2vas.  
function square(r) {
I.  Dominio  Simple   var e = r.stack.pop();
Dado   que   una   función   f   devuelve   un   único   neg( return {
valor  de  retorno,  el  número  de  parámetros  que   square( value: e*e, stack: r.stack
acepta  una  función  g  cuando  se  compone  con  f   {stack:[3]} };
debe   ser   exactamente   uno.   Para   miEgar   este   ) }
function neg(r) {
problema   es   posible   encapsular   los   resultados   );
r.stack.push(-r.value);
de   f   en   una   estructura   de   datos   y/o   resolver   return r;
todos   los   parámetros   de   g   menos   uno   por   }
medio  de  evaluación  parcial  

count( [String]-> Number


words( String -> [String] II.  CompaQbilidad  Rango-­‐Dominio  
clean(s) String -> String F   El   Epo   del   parámetro   de   entrada   de   una  
) función   debe   ser   compaEble   con   el   Epo   del  
); T
valor   de   retorno   devuelto   por   la   función  
G   anterior   para   que   la   composición   pueda  
El  Epo  de  salida  T  debe  ser  compaEble  con   U arEcularse  con  éxito  
el   Epo   de   entrada   U.   En   términos   OOP  
diríamos  que  T  debe  ser  subEpo  de  U  

39     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


F.  Transformación  Monádica  
El  diseño  de  funciones  debe  hacerse  garan2zando  la  ausencia  de  efectos  colaterales  de  manera  
que  cada  función  sólo  dependa  de  sus  parámetros  de  entrada.  Sin  embargo,    en  el  mundo  real  
es   frecuente   requerir   que   una   función   realice   operaciones   que   dependan   del   entorno  
(dependencias  de  estado,  operaciones  de  E/S,  etc.).  Las  técnicas  de  transformación  monádica  
garan2zan  la  ausencia  de  efectos  colaterales  a  la  vez  que    conservan  la  capacidad  composi2va.  
 
Ejemplo.  Monada  Escritor  
 
Supongamos   que   tenemos   una   function inv (x) { console.log('invertir'); return 1/x; }
librería   de   funciones   matemáEcas   function sqr (x) { console.log('cuadrado'); return x*x; }
de   un   solo   parámetro   que   operan   function inc (x) { console.log('incremento'); return x+1; }
con   números   y   devuelven   un   function dec (x) { console.log('decremento'); return x-1; }
número.   Por   moEvos   de   depuración  
estas   funciones   emiten   mensajes   a  
la  consola   Dado   que   la   traza   por   consola   se  
considera   un   efecto   colateral  
indeseable   se   transforman   las  
function inv (x) { return { value: 1/x, log: ['invertir'] }; } funciones   en   puras   parametrizando  
function sqr (x) { return { value: x*x, log: ['cuadrado'] }; } la  traza  como  valor  anexo  de  salida  
function inc (x) { return { value: x+1, log: ['incrementar'] }; }
function dec (x) { return { value: x-1, log: ['decrementar'] }; }

40     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


F.  Transformación  Monádica  
El  diseño  de  funciones  debe  hacerse  garan2zando  la  ausencia  de  efectos  colaterales  de  manera  
que  cada  función  sólo  dependa  de  sus  parámetros  de  entrada.  Sin  embargo,    en  el  mundo  real  
es   frecuente   requerir   que   una   función   realice   operaciones   que   dependan   del   entorno  
(dependencias  de  estado,  operaciones  de  E/S,  etc.).  Las  técnicas  de  transformación  monádica  
garan2zan  la  ausencia  de  efectos  colaterales  a  la  vez  que    conservan  la  capacidad  composi2va.  
 
Ejemplo.  Monada  Escritor  
 
function unit (value) {
Ahora   las   funciones   son   puras   pero   han   perdido   su   return {
capacidad   composiEva   puesto   que   incumplen   la   value: value,
log : []
regla   de   compaEbilidad   Rango-­‐Dominio.   Es  
};
necesario,   en   primer   lugar,   crear   una   función   unit   }
que   eleve   valores   unitarios   desde   el   Epo   simple  
(Number)  al  Epo  monádico  (valor  +  log)  

function bind (m, fn) { Ahora   podemos   crear   una   función   bind   que   permita   componer  
var r = fn(m.value); nuestras   funciones   anteriores   sin   necesidad   de   alterarlas.   Esta  
return { función   recibe   un   valor   monádico   (entrada   +   log   acumulado)   y  
value : r.value, una  de  nuestras  funciones.  La  función  bind  primero  desenvuelve  
log : m.log.concat(r.log)
la  monada,  después  aplica  la  función  pasada  como  parámetro  y  
};
anexa   la   traza   de   la   misma   al   log   acumulado.   Finalmente  
return this;
} devuelve  la  estructura  monádica  con  los  resultados  obtenidos  

41     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


F.  Transformación  Monádica  
El  diseño  de  funciones  debe  hacerse  garan2zando  la  ausencia  de  efectos  colaterales  de  manera  
que  cada  función  sólo  dependa  de  sus  parámetros  de  entrada.  Sin  embargo,    en  el  mundo  real  
es   frecuente   requerir   que   una   función   realice   operaciones   que   dependan   del   entorno  
(dependencias  de  estado,  operaciones  de  E/S,  etc.).  Las  técnicas  de  transformación  monádica  
garan2zan  la  ausencia  de  efectos  colaterales  a  la  vez  que    conservan  la  capacidad  composi2va.  
 
Ejemplo.  Monada  Escritor  
  unit  
3
Con   las   funciones   de   transformación   monádica  
unit   &   bind   hemos   creado   una   solución   para   sqr  
garanEzar   la   composición   funcional   eliminando  
los  efectos  colaterales  de  traza  por  pantalla   inc   { value: 10,
log: [
'cuadrado',
'incremento']
}

bind(
El  valor  primiEvo  3,  se  transforma  primero  al  Epo  
bind(
unit(3), sqr monádico  y  luego  se  compone  con  la  función  sqr  
), neg e  inc  por  medio  de  la  asistencia  que  proporciona  
); la  función  bind  

42     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


F.  Transformación  Monádica  
El  diseño  de  funciones  debe  hacerse  garan2zando  la  ausencia  de  efectos  colaterales  de  manera  
que  cada  función  sólo  dependa  de  sus  parámetros  de  entrada.  Sin  embargo,    en  el  mundo  real  
es   frecuente   requerir   que   una   función   realice   operaciones   que   dependan   del   entorno  
(dependencias  de  estado,  operaciones  de  E/S,  etc.).  Las  técnicas  de  transformación  monádica  
garan2zan  la  ausencia  de  efectos  colaterales  a  la  vez  que    conservan  la  capacidad  composi2va.  
 
Ejemplo.  Monada  Escritor  
 
function Writer (value) { Existen  muchos  Epos  de  efectos  colaterales  que  pueden  
this.value = value; evitarse   por   medio   de   la   aplicación   de   técnicas   de  
this.log = []; composición   monádica.   Dado   que   cada   Epo   de   efecto  
} colateral   requiere   una   lógica   unit   y   bind   específica   es  
Writer.prototype.bind = function (fn) {
buena  idea  expresar  estas  técnicas  como  objetos  donde  
var m = fn(this.value);
unit  se  codifique  como  constructor  y  bind  como  método  
var result = new Writer(m.value);
result.log = this.log.concat(m.log); miembro  del  protoEpo  
return result;
};

Aunque   desde   un   punto   de   vista   pragmáEco   var r = new Writer(3)


esta   operaEva   resulta   cómoda   y   natural   .bind(sqr)
debemos  ser  conscientes  de  que  se  apoya  en   .bind(inc);
encapsulación  de  estado  

43     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


G.  Inversión  de  Control  
Las  programación  funcional  permite  ar2cular  dos  2pos  de  arquitecturas  complementarias.  Las  
arquitecturas  centradas  en  los  datos  fijan  una  colección  de  datos  de  entrada  y  hacen  atravesar  
en   torno   a   ellos   una   colección   de   transformaciones   funcionales.   Ortogonalmente,   las  
arquitecturas  centradas  en  la  transformación  establecen  una  cadena  composi2va  de  funciones  
que  es  atravesada  por  diversas  colecciones  de  datos.  Las  técnicas  de  inversión  de  control  son  
una  pasarela  para  conver2r  un  esquema  arquitectónico  en  el  contrario  y  viceversa.  
 
Arquitecturas  Centradas  en  los  Datos  
 
function data (value) { Las  arquitecturas  centradas  en  los  datos  fijan  un  
conjunto   de   datos   y   permiten   realizar  
return { transformaciones   pasadas   como   parámetros   en  
value: value, orden  superior  
do: function (fn) {
this.value = fn(this.value);
return this; count   words   clean   S 5
}
};
}
data('La FP en JS Mola!!!')
.do(clean)
.do(words)
.do(count);

44     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Técnicas  de  Programación  Funcional  

II.  Técnicas  de  Programación  Funcional  


G.  Inversión  de  Control  
Las  programación  funcional  permite  ar2cular  dos  2pos  de  arquitecturas  complementarias.  Las  
arquitecturas  centradas  en  los  datos  fijan  una  colección  de  datos  de  entrada  y  hacen  atravesar  
en   torno   a   ellos   una   colección   de   transformaciones   funcionales.   Ortogonalmente,   las  
arquitecturas  centradas  en  la  transformación  establecen  una  cadena  composi2va  de  funciones  
que  es  atravesada  por  diversas  colecciones  de  datos.  Las  técnicas  de  inversión  de  control  son  
una  pasarela  para  conver2r  un  esquema  arquitectónico  en  el  contrario  y  viceversa.  
 
Arquitecturas  Centradas  en  la  Transformación  
 
function clean (s) { return s.trim(); } Las   arquitecturas   centradas   en   la   transformación  
function words (s) { return s.split(' '); } establecen   una   cadena   de   composición   de  
function count (s) { return s.length; } transformaciones   funcionales   por   las   que  
atraviesan  disEntas  colecciones  de  datos  
count(
words(
clean('La FP en JS Mola!!!')
) S clean   words   count   5
);

En   el   siguiente   capítulo   estudiaremos   patrones  


dedicados   a   establecer   transformaciones   para  
converEr   arquitecturas   centradas   en   los   datos   a  
arquitecturas   centradas   en   transformación   y  
viceversa  

45     @javiervelezreye  
Javier  Vélez  Reyes  
 @javiervelezreye  

4  
[email protected]  

Programación  Funcional  en  JavaScript  


Patrones  de  
Diseño  
Funcional  

Patrones  de  Diseño  Funcional  


§  Adaptación  Funcional  &  Evaluación  Parcial  
§  Decoración  &  Combinación  
§  Secuenciamiento  &  Inversión  de  Control  
§  Programación  Ambiental  &  Frameworks  Funcionales  
§  Op2mización  &  Asincronía  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

I.  Introducción  
Las   técnicas   y   mecanismos   que   se   han   descrito   hasta   ahora   se   presentan   con   frecuencia  
combinadas   para   dar   respuesta   a   problemas   que   aparecen   recurrentemente   en   los   procesos  
de   desarrollo   de   aplicaciones   funcionales   con   obje2vos   claros   y   bien   definidos.   Esto   da   pie   a  
iden2ficar  este  2po  de  prác2cas  como  soluciones  canónicas  de  validez  probada  que  juegan  el  
papel   de   patrones   de   diseño   en   el   marco   de   la   programación   funcional.   A   lo   largo   de   este  
capítulo  describiremos  9  categorías  de  patrones  funcionales.  

Adaptación   Evaluación  Parcial  


   
Los  patrones  de  adaptación   Los  patrones  de  evaluación  
adaptan  funciones  a  dis2ntos   parcial  transforman  funciones  
contextos  de  uso     para  poder  evaluarlas  por  fases  

Decoración   Secuenciamiento   Inversión  de  Control  


     
Los  patrones  de  decoración   Los  patrones  de  secuencia-­‐ Los  patrones  de  inversión  
transforman  funciones   miento  proporcionan  control  de   invierten  el  contrato  funcional  
incluyendo  lógica  de  decoración   flujo  dirigido  por  los  datos   para  adaptarlo  al  contexto  

P.  Ambiental   OpQmización   Asincronía  


     
Los  patrones  de  programación   Los  patrones  de  op2mización   Los  patrones  de  asincronía  
ambiental  definen  entornos  de   transforman  funciones  para   transforman  funciones  para  
definición  funcional   adaptarlas  en  2empo  y  memoria   conver2rlas  en  no  bloqueantes      

47     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

II.  Patrones  de  Adaptación  Funcional  


La  adaptación  funcional  es  una  de  las  capacidades  de  la  programación  funcional  que  persigue  
transformar   el   proto2po   de   una   función   para   adaptarla   a   las   peculiaridades   específicas   del  
contexto   de   explotación.   La   aplicación   de   adaptaciones   convierte   a   las   arquitecturas  
funcionales   en   sistemas   con   alta   plas2cidad   que   permite   alcanzar   cotas   elevadas   de  
reu2lización.  En  esta  sección  presentamos  algunos  patrones  en  este  sen2do.  

Patrón  reverse  
function reverse (fn) { El   patrón   reverse   adapta   una   función  
return function () { pasada   como   parámetro   para   inverEr   el  
var args = [].slice.call(arguments); orden  de  sus  parámetros  de  entrada  
var iargs = [].concat(args).reverse();
return fn.apply(this, iargs);
}; (8,4)   sub   4  
}
rsub = reverse(sub)  
var add = function (x, y) { return x + y; };
var sub = function (x, y) { return x - y; };
(8,4)   rsub   -4  
var radd = reverse (add);
var rsub = reverse (sub);
La  inversión  de  parámetros  no  afecta  a  
radd (2, 8) === add (2, 8); // true las   operaciones   conmutaEvas   (add)  
radd (2, 8) === add (8, 2); // true pero   sí   a   las   que   no   cumplen   esta  
rsub (2, 8) === sub (2, 8); // false propiedad  (sub)    
rsub (2, 8) === sub (8, 2); // true

48     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

II.  Patrones  de  Adaptación  Funcional  


La  adaptación  funcional  es  una  de  las  capacidades  de  la  programación  funcional  que  persigue  
transformar   el   proto2po   de   una   función   para   adaptarla   a   las   peculiaridades   específicas   del  
contexto   de   explotación.   La   aplicación   de   adaptaciones   convierte   a   las   arquitecturas  
funcionales   en   sistemas   con   alta   plas2cidad   que   permite   alcanzar   cotas   elevadas   de  
reu2lización.  En  esta  sección  presentamos  algunos  patrones  en  este  sen2do.  

Patrón  swap  
function swap (fn, p) { El   patrón   swap   adapta   una   función  
return function () { pasada   como   parámetro   para   inverEr   el  
var args = [].slice.call (arguments); orden   de   un   par   de   parámetros   de  
var temp = args[p[0]]; entrada  
args[p[0]] = args[p[1]];
args[p[1]] = temp; (2,3,5)   exp   17  
return fn.apply(this, args);
}; expSwp = swap(exp, [0,2])  
}

var exp = function (x, y, z){ (2,3,5)   expSwp   11  


return x + y * z;
};
var expSwp1 = swap (exp, [0, 1]); La   inversión   de   parámetros   permite  
var expSwp2 = swap (exp, [0, 2]); reinterpretar   expresiones   de   manera  
exp(2,3,5); // 17 transparente   para   el   usuario   externo.  
expSwp1(2,3,5); // 13 Veremos  su  uElidad  más  adelante  
expSwp2(2,3,5); // 11

49     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

II.  Patrones  de  Adaptación  Funcional  


La  adaptación  funcional  es  una  de  las  capacidades  de  la  programación  funcional  que  persigue  
transformar   el   proto2po   de   una   función   para   adaptarla   a   las   peculiaridades   específicas   del  
contexto   de   explotación.   La   aplicación   de   adaptaciones   convierte   a   las   arquitecturas  
funcionales   en   sistemas   con   alta   plas2cidad   que   permite   alcanzar   cotas   elevadas   de  
reu2lización.  En  esta  sección  presentamos  algunos  patrones  en  este  sen2do.  

Patrón  arity  
function arity (n) { El   patrón   arity   adapta   una   función   de  
return function (fn) { manera   que   acepte   exactamente   un  
return function () { número   especifico   de   parámetros  
var args = [].slice.call(arguments, 0, n-1); ignorando  el  resto    
return fn.apply(this, args);
};
}; f(2,3,5)   unary   f(2)  
}

var unary = arity (1);


['1', '2', '3'].map(parseInt)); // Error La   limitación   del   número   de   parámetros   que  
['1', '2', '3'].map(unary(parseInt))); // Ok puede  aceptar  una  función  puede  resultar  muy  úEl  
a  veces.  En  el  ejemplo,  la  función  parseInt  acepta  
un   String   y   opcionalmente   la   base   (radix).   Sin  
embargo   queremos   que   parseInt   consuma  
exactamente   un   parámetro   cada   vez   que   es  
invocado  para  recorrer  adecuadamente  el  array  

50     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

II.  Patrones  de  Adaptación  Funcional  


La  adaptación  funcional  es  una  de  las  capacidades  de  la  programación  funcional  que  persigue  
transformar   el   proto2po   de   una   función   para   adaptarla   a   las   peculiaridades   específicas   del  
contexto   de   explotación.   La   aplicación   de   adaptaciones   convierte   a   las   arquitecturas  
funcionales   en   sistemas   con   alta   plas2cidad   que   permite   alcanzar   cotas   elevadas   de  
reu2lización.  En  esta  sección  presentamos  algunos  patrones  en  este  sen2do.  

Patrón  variadic  
function variadic (fn) { Pretendemos  imitar  la  capacidad  de  elipsis  (args…)  
return function () { que   disponen   otros   lenguajes   como   úlEmo  
var args = [].slice.call(arguments); parámetro.   Diseñamos   una   función   incluyendo   un  
var other = args.splice(0, fn.length-1); úlEmo  parámetro  args:  
return fn.apply(this, other.concat([args]));
}; function foo(x, y, args) {…}  
}
foo(2, 3, 5, 8)   x = 2
y = 3
var basket = variadic ( args = 5  
function (date, user, products){
console.log('[%s] - %s:', date, user); vfoo = variadic(foo)  
console.log(products);
});
basket( vfoo(2, 3, 5, 8)   x = 2
'hoy', 'jvelez', y = 3
'platanos', 'manzanas', 'peras'); args = [5, 8]  

51     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Patrones  de  Evaluación  Parcial  


La  evaluación  parcial  ofrecen  estrategias  de  transformación  funcional  que  permiten  conver2r  
una   función   completa   en   otra   que   se   evalúa   por   fases.   Como   ya   discu2mos   en   el   capítulo   3,  
esta   técnica   resulta   muy   ú2l   para   reducir   la   dimensión   de   una   transformación   de   forma  
progresiva   y   ar2cular   procesos   de   comunicación   entre   funciones   proveedoras   y   funciones  
cliente.  En  esta  sección  describimos  patrones  de  evaluación  parcial.  

Patrón  first  

function first () { El   patrón   first   adapta   una   función  


var fn = arguments [0]; resolviendo  los  n  primeros  parámetros  de  
var params = [].slice.call(arguments, 1); la  misma  
return function () {
var args = [].slice.call(arguments);
(192,168,1,1)   ip   [192,168,1,1]  
return fn.apply(this, params.concat(args));
};
}
prvIp = first(ip, 192, 168)  

var ip = function (a, b, c, d) {


return [a, b, c, d]; [192,168]  
}; (1,1)   prvIp   [192,168,1,1]  
var prvIp = first(ip, 192, 168);
var pubIp = first(ip, 62, 27);
prvIp(15, 12); // [192,168,15,12]
pubIp(23, 31); // [62,27,23,31]

52     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Patrones  de  Evaluación  Parcial  


La  evaluación  parcial  ofrecen  estrategias  de  transformación  funcional  que  permiten  conver2r  
una   función   completa   en   otra   que   se   evalúa   por   fases.   Como   ya   discu2mos   en   el   capítulo   3,  
esta   técnica   resulta   muy   ú2l   para   reducir   la   dimensión   de   una   transformación   de   forma  
progresiva   y   ar2cular   procesos   de   comunicación   entre   funciones   proveedoras   y   funciones  
cliente.  En  esta  sección  describimos  patrones  de  evaluación  parcial.  

Patrón  last  

function last () { De   manera   complementaria,   el   patrón  


var fn = arguments[0]; last   adapta   una   función   resolviendo   los   n  
var params = [].slice.call(arguments, 1); úlEmos  parámetros  de  la  misma  
return function () {
var args = [].slice.call(arguments);
(192,168,1,1)   ip   [192,168,1,1]  
return fn.apply(this, args.concat(params));
};
}
gwIp = last(ip, 1, 1)  

var gwIp = last(ip, 1, 1);


var prvGw = last(prvIp, 1, 1); [1, 1]  
var pubGw = last(pubIp, 1, 1); (192,168)   gwIp   [192,168,1,1]  
gwIp(192, 168); // [192,168,1,1]
prvGw(); // [192,168,1,1]
pubGw(); // [62,27,1,1]

53     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Patrones  de  Evaluación  Parcial  


La  evaluación  parcial  ofrecen  estrategias  de  transformación  funcional  que  permiten  conver2r  
una   función   completa   en   otra   que   se   evalúa   por   fases.   Como   ya   discu2mos   en   el   capítulo   3,  
esta   técnica   resulta   muy   ú2l   para   reducir   la   dimensión   de   una   transformación   de   forma  
progresiva   y   ar2cular   procesos   de   comunicación   entre   funciones   proveedoras   y   funciones  
cliente.  En  esta  sección  describimos  patrones  de  evaluación  parcial.  

Patrón  parQal  &  rparQal  

function partial (fn) { var add = partial(function (x, y) { return x + y });


return function (x) { var sub = rpartial(function (x, y) { return x - y });
return function (y) { var inc = add(1);
return fn.call(this, x, y); var dec = sub(1);
};
}; [inc(3), dec(4)];
}

function rpartial (fn) { (2,3)   5  


add  
return function (x) {
return function (y) {
add = partial(add)  
return fn.call(this, y, x);
};
}; 2   add  
} El   patrón   parEal   proyecta  
3   5   en   la   dimensión   temporal  
El   patrón   parEal   puede   add(2)   una   función   binaria   en   dos  
evaluarse   a   izquierdas   o   a   fases  de  evaluación  
derechas    
54     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Patrones  de  Evaluación  Parcial  


La  evaluación  parcial  ofrecen  estrategias  de  transformación  funcional  que  permiten  conver2r  
una   función   completa   en   otra   que   se   evalúa   por   fases.   Como   ya   discu2mos   en   el   capítulo   3,  
esta   técnica   resulta   muy   ú2l   para   reducir   la   dimensión   de   una   transformación   de   forma  
progresiva   y   ar2cular   procesos   de   comunicación   entre   funciones   proveedoras   y   funciones  
cliente.  En  esta  sección  describimos  patrones  de  evaluación  parcial.  

Patrón  curry  
La   aplicación   de   los   parámetros   a   la  
function curry (fn) {
función   currificada   puede   aplicarse   de  
return (function aux (args) { forma   flexible   cuando   se   dispongan   sus  
if (args.length >= fn.length) { valores.   Eso   si,   los   parámetros   siempre  
return fn.apply(this, args); deben  aplicarse  en  orden  
}
else return function () {
var nargs = [].slice.call(arguments); var Ip = function (a, b, c, d) {
return aux(args.concat(nargs)); return [a, b, c, d];
}; };
})([]); var cIp = curry(Ip);
}
[ cIp(192, 168, 1, 1),
f   cIp(192, 168, 1)(1),
a   cIp(192, 168)(1, 1),
El   patrón   curry   exEende   el   cIp(192, 168)(1)(1),
patrón   parEal   para   aplicarlo   b  
cIp(192)(168, 1, 1),
a   funciones   con   cualquier   (a,b,c)   f   r  
c   cIp(192)(168, 1)(1)]
número  de  parámetros  
r  

55     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Patrones  de  Evaluación  Parcial  


La  evaluación  parcial  ofrecen  estrategias  de  transformación  funcional  que  permiten  conver2r  
una   función   completa   en   otra   que   se   evalúa   por   fases.   Como   ya   discu2mos   en   el   capítulo   3,  
esta   técnica   resulta   muy   ú2l   para   reducir   la   dimensión   de   una   transformación   de   forma  
progresiva   y   ar2cular   procesos   de   comunicación   entre   funciones   proveedoras   y   funciones  
cliente.  En  esta  sección  describimos  patrones  de  evaluación  parcial.  

Patrón  rcurry   El   patrón   rcurry   funciona   de   manera  


inversa   a   curry   pero   Eene   una   forma   de  
function curry (fn) { uso   parEcular   cada   fase   rellena  
return (function aux (args) { parámetros   por   el   final   pero   el   orden   de  
if (args.length >= fn.length) { aplicación   de   ellos   en   cada   fase   es   de  
return fn.apply(this, args); izquierda  a  derecha  
}
else return function () {
var nargs = [].slice.call(arguments); var Ip = function (a, b, c, d) {
return aux(nargs.concat(args)); return [a, b, c, d];
}; };
})([]); var rcIp = rcurry(Ip);
}
[ rcIp(192, 168, 1, 1),
f   rcIp(168, 1, 1)(192),
c   rcIp(1, 1)(192, 168),
El   patrón   rcurry   exEende   el   rcIp(1, 1)(168)(192),
patrón   parEal   para   aplicarlo   b  
rcIp(1)(192, 168, 1),
a   funciones   con   cualquier   (a,b,c)   f   r  
a   rcIp(1)(168, 1)(192)]
número  de  parámetros  
r  

56     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Patrones  de  Evaluación  Parcial  


La  evaluación  parcial  ofrecen  estrategias  de  transformación  funcional  que  permiten  conver2r  
una   función   completa   en   otra   que   se   evalúa   por   fases.   Como   ya   discu2mos   en   el   capítulo   3,  
esta   técnica   resulta   muy   ú2l   para   reducir   la   dimensión   de   una   transformación   de   forma  
progresiva   y   ar2cular   procesos   de   comunicación   entre   funciones   proveedoras   y   funciones  
cliente.  En  esta  sección  describimos  patrones  de  evaluación  parcial.  

Patrón  uncurry  

function uncurry (fn) { Si   tomamos   una   función   en   aplicación  


return function () { parcial   y   le   aplicamos   el   algoritmo   de  
var args = [].slice.call(arguments); descurrificación   obtenemos   una   función  
return args.reduce(function (ac, arg){ evaluable  en  una  sola  fase  
return (ac = ac(arg));
}, fn);
}; var cadd = function (x) {
} return function (y) {
return function (z) {
return x + y + z;
f   };
a   };
El   patrón   uncurry   deshace   b   (a,b,c)   f   r   };
u n a   c u r r i fi c a c i ó n   p a r a  
obtener   una   función   con   una   c   var add = uncurry (cadd);
única  fase  de  evaluación   cadd(1)(2)(3); // 6
r   add(1,2,3); // 6

57     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

IV.  Patrones  de  Decoración  &  Combinación  


Las   capacidades   adapta2vas   de   la   programación   funcional   permiten   definir   nuevas   funcionas  
resultantes   de   un   proceso   de   decoración   de   funciones   pasadas   en   orden   superior   o   de   una  
combinación   estratégica   de   dos   funciones.   Esto   ofrece   posibilidades   de   intercesión   y  
transformación   funcional   que   flexibilizan   el   uso   de   abstracciones   funcionales   en   diferentes  
contextos  de  uso.  En  esta  sección  presentamos  algunos  patrones  de  este  2po.  

Patrón  Qmes  

function times (n) { El   decorador   Emes   controla   la   ejecución  


return function (fn) { de   una   función   limitando   el   número  
var times = 0; máximo  de  invocaciones  
return function () {
if (times < n) { msj log   >> 'msj'
times++; msj >> 'msj'  
return fn.apply(this, arguments); msj   >> 'msj'  
}
};
}; olog = times(1)(log)  
}
times, n=1  
var log = function (msg) { msj olog   >> 'msj'  
console.log(msg) msj
}; msj  
var olog = times(1)(log);
olog('JS Mola!'); >> JS Mola!
olog('JS Mola!');

58     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

IV.  Patrones  de  Decoración  &  Combinación  


Las   capacidades   adapta2vas   de   la   programación   funcional   permiten   definir   nuevas   funcionas  
resultantes   de   un   proceso   de   decoración   de   funciones   pasadas   en   orden   superior   o   de   una  
combinación   estratégica   de   dos   funciones.   Esto   ofrece   posibilidades   de   intercesión   y  
transformación   funcional   que   flexibilizan   el   uso   de   abstracciones   funcionales   en   diferentes  
contextos  de  uso.  En  esta  sección  presentamos  algunos  patrones  de  este  2po.  

Patrón  maybe  

function maybe (fn) { El   patrón   maybe   comprueba   si   el   número   de  


return function () { parámetros   formales   coincide   con   el   de  
var args = [].slice.call(arguments); argumentos   proporcionados   y   si   ninguno   de   ellos  
var callable = arguments.length >= fn.length && es  null.  Sólo  en  ese  caso  invoca  la  función  
args.every(function (p) {
return (p !== null); (2,3)   5  
add  
});
if (callable) return fn.apply(this, args);
}; mbadd = maybe(add)  
}

(3) mbadd   undefined


var add = function (x, y) { return x + y; }; (2,3) 5  
var mbadd = maybe (add, 2);

console.log(mbadd(3)); // undefined
console.log(mbadd(2, 3)); // 5

59     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

IV.  Patrones  de  Decoración  &  Combinación  


Las   capacidades   adapta2vas   de   la   programación   funcional   permiten   definir   nuevas   funcionas  
resultantes   de   un   proceso   de   decoración   de   funciones   pasadas   en   orden   superior   o   de   una  
combinación   estratégica   de   dos   funciones.   Esto   ofrece   posibilidades   de   intercesión   y  
transformación   funcional   que   flexibilizan   el   uso   de   abstracciones   funcionales   en   diferentes  
contextos  de  uso.  En  esta  sección  presentamos  algunos  patrones  de  este  2po.  

Patrón  before  &  ajer   Los   patrones   before   y   aner   ejecutan   una  
función   decorado   antes   y   después   de   ejecutar  
function before (dn) { la   función   que   se   pasa   como   parámetro   en  
return function (fn) { una  segunda  fase  de  evaluación      
return function () {
dn.apply(this, arguments); (2,3)   5  
add  
return fn.apply(this, arguments);
};
}; afterAdd = after(a)(add);  
}
(2,3)   ajerAdd   5  
function after (dn) { >> 'After'  
return function (fn) {
return function () { var add = function (x, y) { return x + y; };
var r = fn.apply(this, arguments); var b = function () { console.log ('Before'); };
dn.apply(this, arguments); var a = function () { console.log ('After'); };
return r; var beforeAdd = before(b)(add);
}; var afterAdd = before(a)(add);
}; beforeAdd (2,3); // >> 'Before' 5
} afterAdd (2,3); // 5 >> 'After'

60     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

IV.  Patrones  de  Decoración  &  Combinación  


Las   capacidades   adapta2vas   de   la   programación   funcional   permiten   definir   nuevas   funcionas  
resultantes   de   un   proceso   de   decoración   de   funciones   pasadas   en   orden   superior   o   de   una  
combinación   estratégica   de   dos   funciones.   Esto   ofrece   posibilidades   de   intercesión   y  
transformación   funcional   que   flexibilizan   el   uso   de   abstracciones   funcionales   en   diferentes  
contextos  de  uso.  En  esta  sección  presentamos  algunos  patrones  de  este  2po.  

Patrón  around  

function around (dn) { El   patrón   around   permite   diseñar   funciones   que  


return function (fn) { reciben  como  primer  parámetro  una  función  que  
return function () { representa   un   punto   de   intercesión   donde   se  
var args = [].slice.call(arguments);
inyecta  código  desde  el  exterior  
args = [dn.bind(this)].concat(args);
return fn.apply(this, args);
}; (2,3)   add   5  
};
} gAdd = around(g)(add);  

var add = function (around, x, y) { (2,3)   gAdd   g(); g(); 5  


around();
x = x + y;
around(); Dentro   de   la   definición   de   la   función  
return x; add,  around  ()  supone  una  invocación  a  
}; la   función   g,   que   es   inyectada   por   el  
var gAdd = around(g)(add);
cliente  
gAdd(2,3);

61     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

IV.  Patrones  de  Decoración  &  Combinación  


Las   capacidades   adapta2vas   de   la   programación   funcional   permiten   definir   nuevas   funcionas  
resultantes   de   un   proceso   de   decoración   de   funciones   pasadas   en   orden   superior   o   de   una  
combinación   estratégica   de   dos   funciones.   Esto   ofrece   posibilidades   de   intercesión   y  
transformación   funcional   que   flexibilizan   el   uso   de   abstracciones   funcionales   en   diferentes  
contextos  de  uso.  En  esta  sección  presentamos  algunos  patrones  de  este  2po.  

Patrón  provided  &  except   Los   patrones   provided   y   except   ejecutan  


condicionalmente   una   función   cuando   se  
function provided (pn) { saEsface   o   no,   respecEvamente   un   predicado  
return function (fn) { lógico  pasado  como  argumento    
return function () {
if (pn.apply(this, arguments)) (2,3)   add   5  
return fn.apply(this, arguments);
}; padd = provided(positive)(add);  
};
}
(2,3) padd   5
(-2,3)   undefined  
function except (pn) {
return function (fn) {
return function () { var add = function (x, y) { return x+y; };
if (!pn.apply(this, arguments)) var positive = function (x, y) { return x*y>0; };
return fn.apply(this, arguments); var padd = provided(positive)(add);
}; var eadd = except(positive)(add);
};
} [padd(2, 3), padd(-2, 3)]; // [5, undefined]
[eadd(2, 3), eadd(-2, 3)]; // [undefined, 1]

62     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  forEach    
La   función   fn   se   aplica   secuencial-­‐
function forEach (data, fn, self) {
mente   a   todos   los   elementos   de   la  
(function aux (data, index, fn) { f  
colección   desde   el   primero   al  
fn.call(self, data[index], index, data);
if (index < data.length - 1) úlEmo   f  
3
aux(data, index + 1, fn);
f  
})(data, 0, fn); 2
}
1
El   patrón   forEach   encapsula   una  
forEach ([1,2,3], function (item, idx) { inmersión   por   recorrido   de   la  
console.log(idx, item); colección   pasada   como   primer  
}); parámetro  

La  función  manejadora  sigue  un  contrato  basado  en  tres  


parámetros.  El  primero  corresponde  con  el  elemento  en  
curso,   el   segundo   con   el   índice   que   ocupa   dentro   de   la  
colección  y  el  tercero  con  la  propia  colección  

63     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  reduce  
La   función   f   combina   secuencial-­‐
function reduce (data, fn, base, self) {
mente   cada   elemento   de   la  
var ac = base; f  
colección  tomando  el  0  como  valor  
forEach(data, function(e, i, data) {
ac = fn.call(self, ac, data[i], i, data); inicial   f  
3
}, self);
f  
return ac; 2
}
1 0
El   patrón   reduce   encapsula   una  
reduce ([1,2,3], function (a, e) { inmersión  por  acumulación  de  la  
return e + a; colección   pasada   como   primer  
}, 0); parámetro.   La   implementación  
interna  se  apoya  en  forEach    
La   función   manejadora   sigue   un   contrato   basado   en   cuatro  
parámetros.   El   primero   corresponde   con   el   acumulador,   el  
segundo   con   el   elemento   en   curso,   el   tercero   con   el   índice  
que   ocupa   dentro   de   la   colección   y   el   úlEmo   con   la   propia  
colección  

64     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  rReduce  
La   función   f   combina   secuencial-­‐
function rReduce (data, fn, base, self) {
mente   en   orden   inverso   cada  
var iData= [].concat(data).reverse(); f  
elemento   de   la   colección   tomando  
return reduce(iData, fn, base, self);
} el  0  como  valor  inicial   f  
1
f  
2
rReduce ([1,2,3], function (a, e) {
return e + a; 3 0
}, 0); El  carácter  asociaEvo  de  la  operación  de  
suma   provoca   que   el   resultado   sea  
equivalente   al   anterior.   Su   implementa-­‐
La   función   manejadora   sigue   un   contrato   basado   en   cuatro   ción   interna   aplica   un   reduce   sobre   la  
parámetros.   El   primero   corresponde   con   el   acumulador,   el   inversión  del  orden  de  la  colección  
segundo   con   el   elemento   en   curso,   el   tercero   con   el   índice  
que   ocupa   dentro   de   la   colección   y   el   úlEmo   con   la   propia  
colección  

65     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  map  
La   función   f   se   aplica   secuencial-­‐
function map (data, fn, self) {
mente   a   cada   elemento   de   la  
return reduce(data, function (ac, item) { f   9
colección   y   genera   como   resultado  
return ac.concat(fn.call(self, item));
}, [], self); una  nueva  colección  transformada   f   4
3
}
f   1
2

1
map([1,2,3], function (e) { El   patrón   map   se   implementa   interna-­‐
return e * e;
mente   aplicando   una   reducción.   La  
});
estrategia   de   acumulación   consiste   en  
parEr  de  un  array  vacio  e  ir  añadiendo  a  
La   función   manejadora   sigue   un   contrato   basado   en   tres   cada   paso   cada   item   transformado   de  
parámetros.   El   primero   corresponde   con   el   elemento   en   la  colección  al  acumulador  
curso,   el   segundo   con   el   índice   que   ocupa   dentro   de   la  
colección  y  el  tercero  con  la  propia  colección  

66     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  filter  
El  predicado  p  se  aplica  secuencial-­‐
function filter (data, fn, self) {
mente   a   cada   elemento   de   la  
return reduce(data, p   3
colección  y,  si  se  evalúa  a  cierto,  lo  
function (ac, e, i, data) {
if (fn.call(self, e, i, data)) incluye  en  la  colección  de  salida     p   2
3
ac.push(e);
p   1
return ac; 2
}, [], self);
} 1
El   patrón   filter   se   implementa   interna-­‐
mente   aplicando   una   reducción.   La  
filter([1,2,3], function (e){ estrategia   de   acumulación   consiste   en  
return e % 2 !== 0;
parEr  de  un  array  vacio  e  ir  añadiendo  a  
});
cada   paso   cada   item   si   se   supera   el  
predicado  lógico  
La   función   manejadora   es   un   predicado   lógico   que   sigue   un  
contrato  basado  en  tres  parámetros.  El  primero  corresponde  
con  el  elemento  en  curso,  el  segundo  con  el  índice  que  ocupa  
dentro  de  la  colección  y  el  tercero  con  la  propia  colección  

67     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  every  &  some  


El  predicado  p  se  aplica  secuencial-­‐
function every (data, fn, self) {
mente   a   cada   elemento   de   la  
return reduce (data, p  
colección  y  combina  cada  resultado  
function (ac, e, i, data) {
return ac && fn.call(self, e, i, data); a  través  de  la  conjunción  lógica   p  
3
}, true, self);
p  
} 2

function some(data, fn, self) { &&   1 true  


return reduce (data, p  
function (ac, e, i, data) {
return ac || fn.call(self, e, i, data); 3 p  
El  predicado  p  se  aplica  secuencial-­‐
}, false, self);
}
p   mente   a   cada   elemento   de   la  
2 colección  y  combina  cada  resultado  
||   1 false   a  través  de  la  disyunción  lógica  
var p = function (e){return e < 4; };
every([1,2,3], p);
some ([1,2,3], p);

68     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  compose  &  sequence  

function compose (fn, gn) { El   patrón   compose   es   una   función  


return function (x) { de   orden   superior   que   dadas   dos   f   g  
return fn(gn(x)); funciones   devuelve   la   función  
};
compuesta    
}
function sequence (fns) { f  
return function (x) {
return fns.reduce (function (ac, fn) { g  
return fn(ac);
El   patrón   sequence   exEende   la  
}, x); composición   a   una   colección   de  
funciones   tomada   del   primero   al   h  
};
} úlEmo  

function clean (s){ return s.trim(); } sequence([


function words (s){ return s.split(' '); } clean,
function count (s){ return s.length; } words,
compose(count, count
compose(words, clean))('NodeJS Mola'); ])('La FP en JS Mola');

69     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

V.  Patrones  de  Composición  &  Secuenciamiento  


La   programación   funcional   está   basada   en   la   construcción   de   abstracciones   descritas   como  
expresiones  funcionales.  El  concepto  de  secuenciamiento  algorítmico  y  de  control  de  flujo,  tal  
y  como  se  en2ende  en  la  programación  impera2va,  no  es  de  aplicación  en  este  paradigma.  Los  
patrones   de   secuenciamiento   desvelan   formas   con   las   que   es   posible   emular   hasta   cierto  
punto  un  es2lo  de  programación  secuencial  con  direc2vas  de  control  de  flujo.    

Patrón  composeBreak  &  sequenceBreak   function composeBreak (fn, gn) {


return function (x) {
Este   par   de   patrones   exEende   los  
var r = gn(x);
anteriores   de   manera   que   si   alguna     return (r !== void 0) ? fn(r) : void 0;
función  de  la  cadena  devuelve  null  desiste   };
de  terminar  la  composición     }
function sequenceBreak (fns) {
f   return function (x) {
return fns.reduce (function (ac, fn) {
g   return (ac !== void 0) ? fn(ac) : void 0;
f   g   }, x);
h   };
}

function sqr(x){ return x * x ; } var s = sequenceBreak ([


function grt(x){ if (x > 3) return x; } function sqr (x) { return x * x ; },
function grt (x) { if (x > 10) return x; },
var c = composeBreak(sqr, grt); function inc (x) { return x + 1 ; },
[c(3), c(4)]; // [undefined, 16] ]);
[s(3), s(4)]; // [undefined, 17]

70     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VI.  Patrones  de  Inversión  de  Control    


Como   describimos   en   la   introducción   existen   dos   modelos   arquitectónicos   complementarios  
dentro   de   la   programación   funcional.   Las   arquitecturas   centradas   en   los   datos   fijan   un  
conjunto  de  datos  y  sobre  él  aplican  una  cadena  de  transformaciones.  Complementariamente  
es   posible   inver2r   este   modelo   de   control   y   pasar   a   un   modelo   arquitectónico   donde   una  
cadena  funcional  queda  fija  y  son  los  datos  los  que  la  atraviesan.  

Patrón  tap  

function tap (args) {


return function (fn) { El   patrón   tap   invierte   el   control   sobre   la   invocación  
return fn.apply(this, args); funcional   de   manera   que   primero   se   captura   un  
}; conjunto   de   datos   y   luego   se   pueden   aplicar   diferentes  
} funciones  sobre  ellos  

var add = function (x, y) { return x + y; }; (8,4)   add   12   (8,4)   sub   4  


var sub = function (x, y) { return x - y; };
var mul = function (x, y) { return x * y; };
var div = function (x, y) { return x / y; }; data = tap([8,4])  

var data = tap([8,4]);


[8,4]   [8,4]  
[data(add), data(sub), data(mul), data(div)]
add   data   12   sub   data   4  

71     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VI.  Patrones  de  Inversión  de  Control    


Como   describimos   en   la   introducción   existen   dos   modelos   arquitectónicos   complementarios  
dentro   de   la   programación   funcional.   Las   arquitecturas   centradas   en   los   datos   fijan   un  
conjunto  de  datos  y  sobre  él  aplican  una  cadena  de  transformaciones.  Complementariamente  
es   posible   inver2r   este   modelo   de   control   y   pasar   a   un   modelo   arquitectónico   donde   una  
cadena  funcional  queda  fija  y  son  los  datos  los  que  la  atraviesan.  

Patrón  doWith  &  {map,  reduce,  filter,  every,  some}With   El   patrón   doWith   cambia   el   orden   de   aplicación   de  
los   parámetros   colección   y   manejador   de   las  
function doWith (fn) { funciones  de  secuenciamiento  (map,  reduce,  filter…)  
return function (hn) { aplicando   evaluación   parcial   para   obtener   inversión  
return function () { de  control    
var args = [].slice.call(arguments);
args.splice(1, 0, hn); ([1,2,3],sqr)   map   [1,4,9]  
return fn.apply(this, args);
}; mapWith = doWith(map)  
};
} map  
var mapWith = doWith(map);
var reduceWith = doWith(reduce); fn   mapWith   map(_, fn)  
var filterWith = doWith(filter);
var everyWith = doWith(every);
var someWith = doWith(some); mapWithSqr = mapWith(sqr)  

sqr  
var sqr = function (x) { return x*x; };
var mapWithSqr = mapWith(sqr); [1,2,3]   mapWithSqr   map([1,2,3], sqr)  
mapWithSqr([1,2,3]) // [1,4,9]

72     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VI.  Patrones  de  Inversión  de  Control    


Como   describimos   en   la   introducción   existen   dos   modelos   arquitectónicos   complementarios  
dentro   de   la   programación   funcional.   Las   arquitecturas   centradas   en   los   datos   fijan   un  
conjunto  de  datos  y  sobre  él  aplican  una  cadena  de  transformaciones.  Complementariamente  
es   posible   inver2r   este   modelo   de   control   y   pasar   a   un   modelo   arquitectónico   donde   una  
cadena  funcional  queda  fija  y  son  los  datos  los  que  la  atraviesan.  

Patrón  flip   El  patrón  flip  es  equivalente  en  propósito  a  doWith  con  
la   diferencia   que   éste   se   aplica   a   la   versión   de   los  
function flip (fn) { patrones   secuenciales   de   JS   que   se   encuentran   en   el  
return function () {
var args = [].slice.call (arguments);
protoEpo  Array  
return function (second) {
return fn.apply(second, args); ([1,2,3],sqr)   map   [1,4,9]  
};
}; mapWith = flip(map)  
}
map  
var mapWith = flip([].map);
var reduceWith = flip([].reduce); sqr   mapWith   mapWithSqr  
var filterWith = flip([].filter);
var everyWith = flip([].every);
var someWith = flip([].some); mapWithSqr = mapWith(sqr)  

sqr  
var sqr = function (x) { return x*x; };
var mapWithSqr = mapWith(sqr); [1,2,3]   mapWithSqr   [1,4,9]  
mapWithSqr([1,2,3]) // [1,4,9]

73     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VI.  Patrones  de  Inversión  de  Control    


Como   describimos   en   la   introducción   existen   dos   modelos   arquitectónicos   complementarios  
dentro   de   la   programación   funcional.   Las   arquitecturas   centradas   en   los   datos   fijan   un  
conjunto  de  datos  y  sobre  él  aplican  una  cadena  de  transformaciones.  Complementariamente  
es   posible   inver2r   este   modelo   de   control   y   pasar   a   un   modelo   arquitectónico   donde   una  
cadena  funcional  queda  fija  y  son  los  datos  los  que  la  atraviesan.  

Patrón  getWith  &  pluckWith  

function getWith (attribute) {


return function (object) { El   patrón   getWith   define   una   función   que  
return object[attribute]; recupera   un   atributo   específico   sobre   cualquier  
}; objeto.   PluckWith   se   apoya   en   mapWith   para  
}; obtener  los  atributos  de  un  Epo  de  una  colección  
de  objetos  
function pluckWith (attribute) {
return mapWith(getWith(attribute)); attribute='y'  
} {x:1, y:2}   2  
getWith  

var accounts = [
attribute='y'  
{ name: 'jvelez', free: 123 },
{ name: 'eperez', free: 315 }, [ {x:1, y:2}, pluckWith   [2, 3, 4]  
{ name: 'jlopez', free: 23 }, {x:2, y:3},
{ name: 'jruiz' , free: 65 } {x:3, y:4} ]  
];
var free = pluckWith('free');
free(accounts); // [123,315,23,65]

74     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VI.  Patrones  de  Inversión  de  Control    


Como   describimos   en   la   introducción   existen   dos   modelos   arquitectónicos   complementarios  
dentro   de   la   programación   funcional.   Las   arquitecturas   centradas   en   los   datos   fijan   un  
conjunto  de  datos  y  sobre  él  aplican  una  cadena  de  transformaciones.  Complementariamente  
es   posible   inver2r   este   modelo   de   control   y   pasar   a   un   modelo   arquitectónico   donde   una  
cadena  funcional  queda  fija  y  son  los  datos  los  que  la  atraviesan.  

Patrón  composeWith  &  sequenceWith   El  patrón  composeWith  solicita  un  dato  a  la  
fuente   beg   y   lo   hace   atravesar   por   la  
function composeWith (fn, gn, beg) { composición  a  la  inversa  
return function () { d?  
return fn(gn(beg())); beg   f   g   g(f(d))  
};
} d
function sequenceWith (fns, beg) { g  
g(f(d))  
return function () { d?  
return fns.reduce (function (ac, fn) { f(d)
La   extensión   a   cadena   f  
return fn(ac); d?  
}, beg()); funcional   de   composeWith  
}; es  la  función  sequenceWith   d
beg  
}

var data() = // 3, 4, ... var data = function () { return 3; };


var s = sequenceBreakWith ([ var neg = function neg (x) { return -x; };
neg, sqr var sqr = function sqr (x) { return x*x; };
], data); var sqrNeg = composeWith (neg, sqr, data);
[s(), s()]; // [undefined, 17] sqrNeg (); // -9

75     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VI.  Patrones  de  Inversión  de  Control    


Como   describimos   en   la   introducción   existen   dos   modelos   arquitectónicos   complementarios  
dentro   de   la   programación   funcional.   Las   arquitecturas   centradas   en   los   datos   fijan   un  
conjunto  de  datos  y  sobre  él  aplican  una  cadena  de  transformaciones.  Complementariamente  
es   posible   inver2r   este   modelo   de   control   y   pasar   a   un   modelo   arquitectónico   donde   una  
cadena  funcional  queda  fija  y  son  los  datos  los  que  la  atraviesan.  

Patrón  {compose  &  sequence}BreakWith   function composeBreakWith (fn, gn, beg) {


return function () {
Este   par   de   patrones   exEende   los   anteriores   de  
var r = gn(beg());
manera   que   si   alguna     función   de   la   cadena   return (r !== void 0) ? fn(r) : void 0;
devuelve  null  desiste  de  terminar  la  composición     }; }
g   function sequenceBreakWith (fns, beg) {
g(f(d))  
d?   return function () {
f(d) return fns.reduce(function(ac, fn) {
f  
d?   return (ac !== void 0) ? fn(ac) : void 0;
d?  
}, beg());
beg   f   dg   d }; }
beg  

var data = function (x) { var data() = // 3, 4, ...


return function () { return x; }; var s = sequenceBreakWith ([
}; function sqr (x) { return x * x; },
function sqr (x) { return x * x ; } function grt (x) { if (x > 10) return x; },
function grt (x) { if (x > 10) return x; } function inc (x) { return x + 1; },
composeBreakWith(grt,sqr,data(3))(); ], data);
composeBreakWith(grt,sqr,data(4))(); // 16 [s(), s()]; // [undefined, 17]

76     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VII.  Patrones  de  Programación  Ambiental  


La   programación   ambiental   es   un   modelo   arquitectónico   en   el   que   el   desarrollo   funcional   se  
apoya  en  un  framework  que  realiza  de  forma  transparente  transformaciones  funcionales  sobre  
el   código   proporcionado.   En   esta   sección   describimos   algunos   de   los   patrones   de   diseño  
protolpicos  de  la  programación  ambiental.  
Patrón  overload  

function overload () { En   patrón   overload   proporciona   un   entono  


var fns = [].slice.call(arguments); de   programación   que   permite   definir  
return function () { variantes   funcionales   diferenciadas   por   el  
var args = [].slice.call(arguments); número   de   parámetros   formales   que   las  
var fn = fns.filter(function (fn) { definen  
return fn.length === args.length;
})[0]; add    
if (fn) return fn.apply(this, args);
}; (2,3)        (x)  
}      (x,  y)   5  
     (x,  y,  z)  
var add = overload(
function (x) { return x; },
function (x, y) { return x + y; }, Se   revisa   secuencialmente   la   aridad  
function (x, y, z){ return x + y + z; }
de   cada   variante   funcional   incluida  
);
en   el   entorno.   La   primera   función  
add(2,3)
add(2,3,5) que  encaja  exactamente  se  evalúa  y  
devuelve  el  resultado  

77     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VII.  Patrones  de  Programación  Ambiental  


La   programación   ambiental   es   un   modelo   arquitectónico   en   el   que   el   desarrollo   funcional   se  
apoya  en  un  framework  que  realiza  de  forma  transparente  transformaciones  funcionales  sobre  
el   código   proporcionado.   En   esta   sección   describimos   algunos   de   los   patrones   de   diseño  
protolpicos  de  la  programación  ambiental.  
En   patrón   cases-­‐when   proporciona   un   entorno   para   definir  
Patrón  cases-­‐when   funciones   por   casos.   Cada   caso   Eene   un   predicado   y   una  
función   asociada.   Los   casos   se   evalúan   en   el   orden   de  
definición    
function when (guard, fn) {
fib  
return function () {
if (guard.apply(this, arguments))
fib(5)    fib(  0  )  
return fn.apply(this, arguments);
};  fib  (  1  )  
}
function cases () {    fib  (  n  )   fib(4)+fib(3)  
var fns = [].slice.call(arguments);
return function () {
var result;
var args = [].slice.call(arguments); var equals = curry(function (x, y) {
fns.forEach(function (fn) { return x === y;
if (result !== void 0) });
result = fn.apply(this, args); ...
}, this); var fib = cases(
return result; when (equals(0), function (n) {return 1; }),
}; when (equals(1), function (n) {return 1; }),
} function (n) { return fib (n-1) + fib (n-2); }
);

78     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VII.  Patrones  de  Programación  Ambiental  


La   programación   ambiental   es   un   modelo   arquitectónico   en   el   que   el   desarrollo   funcional   se  
apoya  en  un  framework  que  realiza  de  forma  transparente  transformaciones  funcionales  sobre  
el   código   proporcionado.   En   esta   sección   describimos   algunos   de   los   patrones   de   diseño  
protolpicos  de  la  programación  ambiental.  
En   patrón   describe-­‐it   proporciona   un   entorno   para   definir   test  
Patrón  describe-­‐it   unitarios.  La  función  recibe  un  Etulo  y  una  colección  de  its  en  
orden  superior  que  ejecuta  en  secuencia  

describe  (‘suite’)  
function it (test, fn) {
return function () {
return {
test : test, it  (‘test1’,  …)  
result : fn.apply(this, arguments)
}; it  (‘test2’,  …)  
{ suite: 'suite', result: [
}; it  (‘test3’,  …)   { test: 'test1', result: true },
} { test: 'test2', result: false }
function describe (suite) { ]}  
return function () {
var its = [].slice.call(arguments);
var results = its.map(function (it){
return it.apply(this, arguments); describe('Test Suite')(
}, this); it('test 1', function () {
return { return 2 + 3 === 5;
suite : suite, }),
result : results it('test 2', function () {
}; return 2 - 3 === 5;
}; })
} );

79     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VIII.  Patrones  de  OpQmización  


La   op2mización   de   código   tanto   en   2empo   como   en   memoria   es   una   de   las   preocupaciones  
esenciales  de  la  programación  cuando  se  abordan  problemas  que  requieren  un  alto  grado  de  
rendimiento.   Los   patrones   de   op2mización   presentan   estrategias   esenciales   acerca   de   cómo  
realizar  trasformaciones  funcionales  abstractas  dirigidas  a  tal  fin.  
Patrón  Qme  

function time (fn) { El  patrón  Eme  permite  medir  el  Eempo  


return function () { que   tarda   una   función   pasada   en  
var before = Date.now(); orden  superior  en  ejecutar    
var result = fn.apply(this, arguments);
var after = Date.now(); before = t0  
return { { result: 832040
fib(5)   fib  (20)   time: 10
value : result,
time : (after - before) after = tn   }
};
};
} Se   pide   una   marca   de   Eempo   al  
sistema  antes  y  después  de  ejecutar  la  
función  y  se  devuelve  un  objeto  con  el  
var fib = function (n) {
resultado   y   la   diferencia   de   Eempos   en  
if (n < 2) return n;
else return fib(n-1) + fib(n-2);
ms    
};
var tfib = time(fib);
tfib(20);

80     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VIII.  Patrones  de  OpQmización  


La   op2mización   de   código   tanto   en   2empo   como   en   memoria   es   una   de   las   preocupaciones  
esenciales  de  la  programación  cuando  se  abordan  problemas  que  requieren  un  alto  grado  de  
rendimiento.   Los   patrones   de   op2mización   presentan   estrategias   esenciales   acerca   de   cómo  
realizar  trasformaciones  funcionales  abstractas  dirigidas  a  tal  fin.  
cache  
Patrón  memoize  
fib(2) 1
function memoize (fn) { fib(3)   2  
var cache = {}; Fib(4)   fib   fib(3)+fib(2)  
var mfn = function () {
var args = [].slice.call (arguments);
var key = JSON.stringify(args); Memoize   reEene   una   cache   interna   sobre   evaluaciones  
return key in cache ? anteriormente   calculadas   dentro   del   proceso   recursivo.  
cache[key] :
Ahora  en  el  árbol  de  acEvación  todas  las  llamadas  en  líneas  
cache[key] = fn.apply(this, args);
}; disconEnuas   no   se   realizan.   Nótese   que   la   memoización   el  
return mfn; código   se   hace   sobre   la   misma   variable   fib   ya   que   es   la  
} única   forma   de   garanEzar   que   en   memoize   se   recurre   sobre  
la  versión  memoizada  de  fn    
fib  (4)  
var fib = function (n) {
if (n < 2) return n;
else return fib(n-1) + fib(n-2); fib  (3)   fib  (2)  
};
var fib = memoize(fib); fib  (2)   fib  (1)   fib  (1)   fib  (0)  
tfib(43);
fib  (1)   fib  (0)  

81     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VIII.  Patrones  de  OpQmización  


La   op2mización   de   código   tanto   en   2empo   como   en   memoria   es   una   de   las   preocupaciones  
esenciales  de  la  programación  cuando  se  abordan  problemas  que  requieren  un  alto  grado  de  
rendimiento.   Los   patrones   de   op2mización   presentan   estrategias   esenciales   acerca   de   cómo  
realizar  trasformaciones  funcionales  abstractas  dirigidas  a  tal  fin.  
Patrón  trampoline  
El  problema  
var f = function (n) { La  función  f  Eene  recursividad  no  final  puesto  que  en  el  caso  recursivo,  
if (n===0) return 1; despues   de   invocar   a   f,   es   necesario   mulEplicar   por   n.   Esto   Eene  
return n*f(n-1); impacto   en   memoria   ya   que   el   compilador   Eene   que   recordar   cada  
}; valor  de  n  para  cada  una  de  las  llamadas  recursivas  a  f.  Los  lenguajes  
var tf = function (n, ac) { con  soporte  a  la  recursividad  uElizan  una  pila  para  gesEonar  esto.  En  
if (n === 0) return ac;
el   ejemplo   vemos   como   f(4)   consume   4*k   espacios   de   memoria   donde  
return tf(n-1, n*ac);
};
k   es   el   tamaño   del   registro   de   acEvación   que   necesita   el   compilador  
para  gesEonar  cada  invocación  

Tail  Recursion.  Una  solución  inúQl  


En  la  versión  q,  se  rediseña  la  función  f  de  manera  que  el  caso  recursivo  no  Eene      0  
operaciones   de   combinación   tras   su   invocación.   A   esto   se   le   llama   diseño   en      1  
recursividad  final  o  tail  recursión  y  para  ello  se  emplean  técnicas  de  inmersión  por  
   2  
acumulador.   Algunos   lenguajes   saben   sacar   parEdo   de   este   Epo   de   diseños  
haciendo  que  las  llamadas  no  se  gesEonen  por  pila  sino  en  una  zona  de  memoria      3  
estáEca.  Aunque  esto  sobrescribe  los  valores  en  cada  invocación  recursiva  no  Eene,      4      4  
por  diseño  en  este  caso,  ningún  efecto  neto  y  sí  un  considerable  ahorro  de  espacio  
f  (4)   u  (4)  
en  memoria.  Lamentablemente  este  no  es  el  caso  de  JavaScript  

82     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

VIII.  Patrones  de  OpQmización  


La   op2mización   de   código   tanto   en   2empo   como   en   memoria   es   una   de   las   preocupaciones  
esenciales  de  la  programación  cuando  se  abordan  problemas  que  requieren  un  alto  grado  de  
rendimiento.   Los   patrones   de   op2mización   presentan   estrategias   esenciales   acerca   de   cómo  
realizar  trasformaciones  funcionales  abstractas  dirigidas  a  tal  fin.  
Patrón  trampoline  
Diseño  por  Thunks  
var ttf = function f(n, ac) { ParEendo   de   la   versión   de   en   recursividad   final   es   posible   crear   un  
if (n === 0) return ac; nuevo   diseño   en   el   que   el   caso   recursivo   no   se   invoca   directamente  
return function (){ sino  que  se  envuelve  en  una  función.  Este  Epo  de  envolturas  recibe  el  
return f(n-1, n*ac); nombre  de  Thunk  y  se  uEliza  como  función  vehicular  para  comunicar  
}; datos  a  un  framework.  El  efecto  neto  en  este  caso  es  que  la  resolución  
};
se  rompe  a  cada  paso  introduciendo  una  fase  de  evaluación  

El  framework  trampoline  
function trampoline (fn) {
Con   este   diseño   la   función   trampoline   juega   el   papel   return function () {
del   framework   encargado   de   desenvolver   dentro   de   var result = fn.apply(this, arguments);
una   iteración   cada   fase   de   envoltura   con   thunk   y   while (result instanceof Function)
acumularla   en   una   variable   de   resultados.   De   esta   result = result();
forma  se  consigue  desarrollar  la  recursividad  sin  hacer   return result;
uso  de  pila   v  (2)  
};
}
v  (1)   var tttf = trampoline(tf);
 0       tttf(5); // 120

83     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  
1  Programación  Asíncrona  en  NodeJS.  En  Slideshare@  jvelez77  

IX.  Patrones  de  Programación  Asíncrona  


La   programación   asíncrona   es   un   modelo   de   programación   en   el   que   algunas   funciones   son   no  
bloqueantes   y   devuelven   el   control   al   programa   llamante   de   manera   instantánea.   Dado   que  
estas   funciones   se   independizan   del   flujo   del   ejecución   central,   es   necesario   proporcionarles  
de  alguna  forma  la  lógica  de  con2nuación  que  prescribe  cómo  procesar  la  respuesta  cuando  la  
función   acabe.   Dado   que   ya   dedicamos   un   documento   entero   a   la   programación   asíncrona1  
nos  centraremos  aquí  en  dar  patrones  para  hacer  invocaciones  asíncronas.  
Patrón  delay  &  async   Los   patrones   delay   y   async   transforman   una  
función  en  no  bloqueante  instantáneamente  y  tras  
function delay (fn, ms) { un  retardo  determinado  respecEvamente  
return function () {
var args = [].slice.call(arguments); async   async  
setTimeout (function () {
async  (log)  
fn.apply(this, args);
}.bind(this), ms);
>>  msg   3000  ms  
};
} >>  msg  
function async (fn) {
return delay(fn, 0); var log = function(msg){ console.log (msg); };
} var dlog = delay(log, 3000);
var alog = async(log);

dlog('NodeJS Madrid Mola!!!');


alog('NodeJS Madrid Mola!!!');

84     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  
1  Programación  Asíncrona  en  NodeJS.  En  Slideshare@  jvelez77  

IX.  Patrones  de  Programación  Asíncrona  


La   programación   asíncrona   es   un   modelo   de   programación   en   el   que   algunas   funciones   son   no  
bloqueantes   y   devuelven   el   control   al   programa   llamante   de   manera   instantánea.   Dado   que  
estas   funciones   se   independizan   del   flujo   del   ejecución   central,   es   necesario   proporcionarles  
de  alguna  forma  la  lógica  de  con2nuación  que  prescribe  cómo  procesar  la  respuesta  cuando  la  
función   acabe.   Dado   que   ya   dedicamos   un   documento   entero   a   la   programación   asíncrona1  
nos  centraremos  aquí  en  dar  patrones  para  hacer  invocaciones  asíncronas.  
Patrón  forever  &  retry   El  patrón  forever  itera  eternamente  una  función  a  intervalos  
de   Eempo   marcados   mientras   que   retry   reintenta   la  
invocación   de   una   función   un   número   de   veces   mientras   se  
function forever (fn, ms) {
return function () { obtenga  un  resultado  no  definido  
var args = [].slice.call(arguments);
setInterval (function () { async   async  
fn.apply(this, args); forever  (log)   retry  (log)  
}.bind(this), ms);
};
3000  ms  
} >>  msg  
function retry (fn, n, ms) { >>  msg  
var idx = 0;
return function aux () {
var r = fn.apply(this, arguments); var log = function(msg){ console.log (msg);};
if (idx < n && !r) { var rlog = retry (log, 3, 1000);
r = delay(fn, ms) var flog = forever (log, 3000);
.apply(this, arguments); idx++; }
return r; rlog ('NodeJS Madrid Mola!!!');
}; } flog ('NodeJS Madrid Mola!!!');

85     @javiervelezreye  
Javier  Vélez  Reyes  
 @javiervelezreye  

5  
[email protected]  

Programación  Funcional  en  Node  JS  


Arquitecturas  de  

Arquitecturas  de  Programación  Funcional  


Programación  
Funcional  

§  Arquitecturas  Map-­‐Reduce  


§  Arquitecturas  Reac2vas  
§  Arquitecturas  Asíncronas  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

I.  Introducción  
En  los  capítulos  anteriores  hemos  presentado  los  mecanismos,  técnicas  y  patrones  de  diseño  
que  se  emplean  en  el  marco  de  la  programación  funcional.  No  obstante,  sobre  esta  base,  es  
posible   definir   es2los   arquitectónicos   propios   por   aplicación   de   una   serie   de   restricciones   en  
relación  a  los  obje2vos  y  principios  de  diseño  que  se  persiguen  para  un  determinado  2po  de  
problemas.  Sin  ánimo  de  comple2tud,  a  lo  largo  de  este  capítulo  presentaremos  una  colección  
de   arquitecturas   funcionales   que   man2enen   actual   vigencia   en   problemas   canónicos   en   la  
prác2ca  empresarial.  El  siguiente  marco  clasifica  la  familia  de  arquitecturas  existentes.  

Relación  Temporal  

Cómo   se   relacionan   las   Síncronas

Secuenciales
transformaciones   funcionales  

Paralelas
en  la  dimensión  temporal  
Asíncronas

Relación  Espacial  
Cómo   se   relacionan   los   transforma-­‐ Req-Res
dores   en   cuanto   a   su   composición   de   Cómo   se   distribuyen   los   datos   en  
forma  directa  o  indirecta   One Way relación   a   los   transformadores  
funcionales  que  los  procesan  
Relación  Nominal  

87     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

I.  Introducción  
A.  Relación  Espacial    
La   relación   espacial   discrimina   cómo   se   distribuyen   los   datos   entre   la   colección   de  
transformadores   funcionales   que   los   procesan.   En   las   arquitecturas   secuenciales,   las   funciones  
se   disponen   composi2vamente   de   manera   que   los   datos   atraviesan   una   cadena   de  
transformaciones   en   cascada.   Las   arquitecturas   paralelas   parten   los   datos   en   conjuntos  
homogéneos  y  operan  sobre  ellos  de  manera  simultánea.  

Arquitecturas  Secuenciales     Arquitecturas  Paralelas  

D  
En  las  arquitecturas  secuenciales   D  
los   datos   atraviesan   en   cascada  
una  cadena  composiEva  
D  
D   D   D  

D  
Las   arquitecturas   paralela   parten  
D  
los   datos   de   forma   homogénea   y  
los  procesan  de  forma  simultanea  

88     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  
1  Programación  Asíncrona  en  NodeJS.  En  Slideshare@  jvelez77  

I.  Introducción  
B.  Relación  Temporal  
La   relación   temporal   clasifica   las   soluciones   en   función   del   carácter   bloqueante   o   no  
bloqueante   de   las   transformaciones   funcionales.   Las   arquitecturas   síncronas   encadenan  
operaciones   bloqueantes   mientras   que   las   asíncronas   invocan   operaciones   no   bloqueantes   y  
con2núan  con  el  flujo  de  procesamiento  normal.  Esto  complica  considerablemente  el  modelo  
de  programación  requiriendo  introducir  con2nuaciones  o  mónadas  de  con2nuidad1.  

Arquitecturas  Síncronas   Arquitecturas  Asíncronas  

En   las   arquitecturas   síncronas   todas  


las   transformaciones   funcionales   son  
bloqueantes   lo   que   implica   que   una  
operación   no   comienza   hasta   que  
termina  la  anterior  

Las   arquitecturas   asíncronas   entrelazan  


operaciones   bloqueantes   y   no   bloqueantes  
de   manera   que   aparecen   varios   flujos   de  
transformación    

89     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

I.  Introducción  
C.  Relación  Nominal  
La  relación  nominal  se  centra  en  describir  las  arquitecturas  atendiendo  al  2po  de  composición  
que   man2enen   las   abstracciones   funcionales   entre   sí.   Se   dis2ngue   entre   arquitecturas  
acopladas  nominalmente,    donde  la  función  llamante  conoce  la  iden2dad  del  des2natario  de  la  
llamada  y  las  arquitecturas  desacopladas  donde  la  iden2dad  es  desconocida  y  el  número  de  los  
receptores  que  a2enden  una  llamada  puede  ser  múl2ple.  

Arquitecturas  Solicitud  Respuesta   Arquitecturas  One  Way  

En  las  arquitecturas  Solicitud  Respuesta  


el   llamante   conoce   la   idenEdad   del   middleware  
llamado   y   cada   llamada   es   atendida  
exactamente  por  un  único  receptor  

En   las   arquitecturas   One   Way,   el   emisor  


n o   c o n o c e   l a   i d e n E d a d   d e   s u s  
desEnatarios   ni   tampoco   la   canEdad   de  
aquéllos  que  atenderán  su  solicitud  

90     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

II.  Arquitecturas  Map-­‐Reduce  


Consideremos  un  dataset  con  información  sobre  los  usuarios  de  twioer.  Cada  registro  incluye  
la   edad   y   el   número   de   contactos.   Se   pretende   hacer   una   consulta   map-­‐reduce   sobre   estos  
datos  para  obtener  un  histograma  de  frecuencias  agrupando  contactos  por  rango  de  edad.    

Fase  I.  Split   function split (dataset, n) {


var results = [];
Split   recibe   el   dataset   y   el   número   de   dataset.forEach(function (item, index) {
segmentos   en   los   que   se   fragmentarán   var batch = index % n;
los   datos.   La   políEca   de   fragmentación   if (results[batch]) results[batch].push(item);
en  este  ejemplo  no  es  importante.  Sólo  se   else results[batch] = [item];
requiere   un   tamaño   homogéneo   entre   });
return results;
los  mismos  
}

function map (batch) { Fase  II.  Map  


return batch.map(function (item) {
return { La   operación   map   recibe   un   segmento   de  
age : item.age, datos  y  lo  enriquece  incluyendo  un  contador  
contacts : item.contacts, a   1.   Este   dato   será   transformado   en   fases  
count : 1 posteriores   del   algoritmo   y   se   empleará   en  
}; la  etapa  de  consolidación  final  
});
}

91     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

II.  Arquitecturas  Map-­‐Reduce  


Consideremos  un  dataset  con  información  sobre  los  usuarios  de  twioer.  Cada  registro  incluye  
la   edad   y   el   número   de   contactos.   Se   pretende   hacer   una   consulta   map-­‐reduce   sobre   estos  
datos  para  obtener  un  histograma  de  frecuencias  agrupando  contactos  por  rango  de  edad.    

Fase  III.  Shuffle   function shuffle (dataset) {


return dataset.reduce(function (ac, item) {
Esta   operación   recibe   toda   la   base   de   var range = Math.floor(item.age / 10);
datos   y   crea   unos   nuevos   segmentos   if (!ac[range]) {
para  cada  rango  de  edad     ac[range] = [];
  }
En   el   ejemplo   se   ha   decidido,   por   ac[range].push({
range : range,
simplicidad,   dividir   la   edad   por   10   para  
age : item.age,
idenEficar   el   rango   de   edad   al   que  
contacts : item.contacts,
pertenece  un  usuario  pero  otros  criterios   count : item.count
más  elaborados  son  posibles   });
  return ac;
Nótese   que   el   propósito   de   esta   }, []);
operación   es   redistribuir   los   datos   de   }
manera   que   cada   nuevo   segmento  
incluya   todos   los   datos   con   una   clave  
común   (en   nuestro   ejemplo   rango   de  
edad)  pero  aún  no  se  aplican  estrategias  
de  reducción  que  son  responsabilidad  de  
la  siguiente  fase      

92     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

II.  Arquitecturas  Map-­‐Reduce  


Consideremos  un  dataset  con  información  sobre  los  usuarios  de  twioer.  Cada  registro  incluye  
la   edad   y   el   número   de   contactos.   Se   pretende   hacer   una   consulta   map-­‐reduce   sobre   estos  
datos  para  obtener  un  histograma  de  frecuencias  agrupando  contactos  por  rango  de  edad.    

Fase  VI.  Shuffle   function reduce (batch) {


return batch.reduce(function (ac, item) {
La  operación  reduce  recibe  un  segmento   ac.range = item.range;
asociado   a   un   rango   de   edad   y   acumula   ac.contacts += item.contacts
el   número   de   contactos   y   el   número   de   ac.count += item.count;
usuarios  dentro  de  ese  rango   return ac;
}, { contacts: 0, count: 0 });
}

function join (dataset) {


return dataset.reduce(function (ac, batch) { Fase  V.  Join  
ac.push({ Finalmente,   la   operación   Join   acumula  
range : batch.range,
todos   los   segmentos   que   agrupan   los  
contacts : batch.contacts,
rangos  de  edad  y  para  cada  uno  de  ellos  
count : batch.count,
freq : batch.contacts / batch.count calcula  sus  frecuencias  relaEvas  
});
return ac;
}, []);
}

93     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

II.  Arquitecturas  Map-­‐Reduce  


Consideremos  un  dataset  con  información  sobre  los  usuarios  de  twioer.  Cada  registro  incluye  
la   edad   y   el   número   de   contactos.   Se   pretende   hacer   una   consulta   map-­‐reduce   sobre   estos  
datos  para  obtener  un  histograma  de  frecuencias  agrupando  contactos  por  rango  de  edad.    

{ age: 17, contacts: 67 }


join (split (dataset, 3) { age: 22, contacts: 45 }
.map (function (batch) { { age: 29, contacts: 34 }
return map(batch); { age: 14, contacts: 34 }  
})
.reduce (function (ac, batch, index, ds) { { age: 17, …} { age: 29, …}
return (index < ds.length-1) ? { age: 22, …} { age: 14, …}  
ac.concat (batch) :
[ac.concat (batch)]; { age: 17, count:1, …} { age: 29, count:1, …}
}, []) { age: 22, count:1, …} { age: 14, count:1, …}  
.reduce (function (ac, ds) {
ac = shuffle (ds);
{ range: 1, count:1, …} { range: 2, count:1, …}
return ac;
{ range: 1, count:1, …} { range: 2, count:1, …}  
}, [])
.reduce (function (ac, batch) {
ac.push (reduce (batch)); { range: 1, count:2, …} { range: 2, count:2, …}
return ac;
}, [])
);
{ range: 1, count:2, …}
{ range: 2, count:2, …}

94     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

Fuente   sequence ([
sqr, compose (inc,
La  fuente  es  la  encargada  de  
grt, compose (grt,
proporcionar   los   datos   a   la   sqr))
inc
cadena  de  transformación   (4);
])(4);
sqr  

Cadena   grt
Cada  operación  toma  un  dato   var data = 2,3,4...
de   entrada   y   lo   transforma   var numbers = Stream (data)
inc
en  otro  de  salida   .map(sqr)
.filter(grt)
.reduce(inc, 0)
.end();
API  fluida   numbers.pull ();
Se   pretende   transitar   de   los   esElos   de   composición   (compose  
&   sequence)   a   un   esElo   de   API   fluida   en   el   que   se   define   la  
composición   encadenando   funciones   con   el   operador   punto  
sobre  un  objeto  de  contexto  proporcionado  por  Stream  

95     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

I.  Modelo  Pull   I.  Modelo  Push  


En  el  modelo  pull,  el  úlEmo  nodo  solicita  nuevos   En  el  modelo  push,  a  medida  que  se  disponen  de  
datos   y   la   solicitud   recorre   ascendentemente   la   nuevos   datos,   la   fuente   los   empuja   por   la   cadena  
cadena  hasta  llegar  a  la  fuente     de  transformación    

La   fuente   es   una   enEdad   La   fuente   es   una   enEdad  


pasiva   que   genera   nuevos   acEva  que  produce  datos  y  los  
datos  bajo  demanda   entrega  a  la  cadena  

96     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

pull  &  push  

function pull(fn, base) {


Las   fuentes   acEvas   corresponden   generalmente   con  
var idx = base || 0; escuchadores  de  eventos.  Para  emular  datos  asíncronos  
return function () { emiEdos  a  intervalos  regulares  usamos  el  patrón  push  
return fn.call(this, idx++);
};
} function push (fn, ms) {
return function (cb) {
var source = pull(fn);
var inc = function (x) { return x + 1; }; setInterval (function () {
var dbl = function (x) { return 2 * x; }; cb(source());
var s1 = pull(inc); }, ms || 1000);
var s2 = pull(dbl); };
[s1(), s1(), s1()] // [0, 1, 2] }
[s2(), s2(), s2()] // [0, 2, 4]

var log = console.log


El   patrón   pull   transforma   un   función   en   un   var delay = 3000;
iterador   con   memoria   que   devuelve   en   cada   push(inc, log, delay); >> 0, 1, 2, ...
invocación  el  siguiente  elemento  de  la  serie   push(dbl, log, delay); >> 0, 2, 4, ...

97     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

emap,  efilter  &  ereduce  


Para  inyectar  las  transformaciones  sobre  la  cadena  de  
c o m p o s i c i ó n ,   s e   u E l i z a n   l o s   p a t r o n e s   d e  
secuenciamiento  pero  en  versión  de  un  solo  dato  en  vez   function ereduce (fn, b) {
de  una  colección   var ac = b;
ereduce(x+1, 0) return function () {
efilter(x%2 === 0) var args = [].slice.call(arguments);
1, 2, 3 1, 3, 6 1, 2, 3 2 ac = fn.apply(this, [ac].concat(args));
return ac;
emap(x*x) };
1, 2, 3 1, 4, 9 }

function efilter (fn) { function emap (fn) {


return function () { return function () {
var out = fn.apply(this, arguments); return fn.apply(this, arguments);
if (out) return arguments[0]; };
}; }
}

98     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

fluent     function fluent (hn) {


var cb = hn || function () {};
Dado  que  cada  operador  (clean,  words,  count)    
return function (fn) {
devuelve   un   dato   transformado,   no   podemos   return function () {
encadenar  sus  llamadas  tal  cual.     cb (fn.apply(this, arguments));
return this;
var data = 2,3,4... };
var numbers = Stream (data) };
.map(sqr) }
.filter(grt)
.reduce(inc, 0)
.end(); sqr  
numbers (); Necesitamos  transformar  los  operadores  a  través  del  
patrón  fluid  que  genera  una  función  para  ejecutar  el  
grt
operador,   entregar   el   resultado   a   un   manejador   y  
devolver   una   referencia   al   objeto   contexto   devuelto  
inc por   Stream   para   poder   seguir   encadenando  
operadores  

99     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  
function pullStream (source) {
Stream  Pull   var fns = [];
var define = fluent(function (fn) {
La   función   define   aplica   fluent   para   fns.push(fn);
registrar   cada   función   manejadora   que   });
introduce   el   cliente   en   map   filter   y   var next = function (fns, beg) {
var result = sequenceBreakWith(fns, beg)();
reduce  en  fns  
return result ? result : next(fns, beg);
};
La   función   next   aplica   sequenceBreakWith   return {
sobre   cada   función   registrada   en   fns   para   map : define(emap),
obtener  una  cadena  de  composición       filter: define(efilter),
reduce: define(ereduce),
end : function () {
Se   devuelve   el   objeto   de   contexto   con   los   return {
métodos  map,  filter  y  reduce  decorados  con   pull: function () {
define.   El   método   end   transforma   el   return next(fns, source);
contexto   en   un   objeto   con   un   método   pull   }
para  explotar  la  cadena     };
}
};
}

100     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

Stream  Pull  
var source = pull (function (x) { return x + 1; }, 0);
Se   define   una   fuente   de   datos   de   var stream = Stream(source)
números  naturales  y  se  aplica  la  cadena   .map (function (e) { return e * e; })
de  transformación  [sqr,  even,  add]   .filter (function (e) { return e % 2 === 0})
.reduce (function (a, e) { return a + e; }, 0)
.end();
stream.pull(); // 0, 4, 20, 50, ...

var source = function s() { return 'NodeJS Mola!' };


var stream = Stream (source) Se  define  una  fuente  de  datos  constante  
.map (function (s) { return s.trim (); }) con  la  cadena  ‘NodeJS  Mola’  y  se  aplica  
.map (function (s) { return s.split (' '); }) la   cadena   [clean,   split,   count]   para  
.map (function (s) { return s.length; }) contar  las  palabras  
.end ();
source.pull(); // 2

101     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  
function pushStream (source) {
Stream  Push   var fns = [];
var lns = [];
La   colección   lns   acumula   los   escucha-­‐ var define = fluent(function (fn) {...});
dores   que   se   registran   al   stream   para   return {
ser  noEficados  de  cada  nuevo  resultado   map : define(emap),
filter: define(efilter),
procesado  
reduce: define(ereduce),
end: function () {
La  función  end  aplica  sequenceBreak  una  vez   var sequence = sequenceBreak(fns);
para   obtener   la   cadena   de   composición   y   source(function (data) {
después  arranca  la  fuente  con  un  manejador   var result = sequence(data);
que   obEene   el   siguiente   resultado   y   si   es   lns.forEach(function (ln) {
definido  lo  publica  a  cada  escuchador   if (result) ln(result);
});
});
Se   devuelve   un   objeto   con   un   método   listen   return {
que   permite   registrar   nuevos   manejadores   listen: function (ln) {
asociados  a  escuchadores  interesados   lns.push(ln); }
};
}
}; }

102     @javiervelezreye  
Programación  Funcional  en  JavaScript  
Patrones  de  Diseño  Funcional  

III.  Arquitecturas  ReacQvas  


Las   arquitecturas   de   programación   reac2va   establecen   cadenas   de   composición   que   son  
atravesadas  por  streams  de  datos.  Cada  operación  dentro  de  la  cadena  se  encarga  de  recibir  
un   dato   cada   vez   y   transformarlo   de   acuerdo   a   determinada   lógica.   En   esta   sección  
describiremos   cómo   funciona   un   framework   de   programación   reac2va   internamente   y  
discu2remos  los  patrones  que  u2liza.  

Stream  Push  
var source = push(function (x) { return x + 1; });
La   fuente   es   ahora   un   emisor   de   datos   var stream = Stream(source)
acEvo   que   funciona   según   el   patrón   .map (function (e) { return e * e; })
push.   Cuando   hay   datos   nuevos,   ésta   .filter (function (e) { return e % 2 === 0})
l o s   e m p u j a   p o r   l a   c a d e n a   d e   .reduce (function (a, e) { return a + e; }, 0)
composición   y   los   publica   encada   uno   .end();
de  los  escuchadores  registrados   stream.listen(console.log);
1, 2, 3,...  

sqr  
lns   Cada   escuchador   interesado   en   ser  
noEficado   de   nuevos   datos   emiEdos   por  
0   el   stream   debe   registrar   una   función  
even manejadora  a  través  del  método  push  
20  
add

0, 20, 50,...  

103     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

IV.  Arquitecturas  Asíncronas  


Las   arquitecturas   asíncronas   establecen   la   posibilidad   de   hacer   que   algunas   operaciones  
devuelvan   el   control   al   programa   llamante   antes   de   que   hayan   terminado   mientras   siguen  
operando   en   segundo   plano.   Esto   agiliza   el   proceso   de   ejecución   y   en   general   permite  
aumentar  la  escalabilidad  pero  complica  el  razonamiento  sobre  el  programa.  

E  0   Ejecución  no  secuencial  


Operaciones  no  bloqueantes   Ya  no  se  manEene  el  orden  secuencial  
S1  
Ahora   algunas   operaciones   son   no   bloqueantes   puesto   que   la   ejecución   de   la  
ya   que   devuelven   el   control   al   programa   E  1   instrucción   que   sigue   a   un   operación  
llamante   antes   de   su   terminación   mientras   E  2’   no   bloqueante   se   adelanta   antes   de  
siguen  ejecutando  en  segundo  plano   que   dicha   no   bloqueante   haya  
S2  
S3   finalizado  

Imposible  razonar  sobre  el  estado   E  3’  


La   falta   de   secuencialidad   estricta   en   la  
ejecución   del   programa   hace   diRcil   determinar   S4  
el  estado  al  comienzo  de  cada  operación  
Aumento  de  la  escalabilidad  
La   asincronía   permite   que   los  
siguientes   procesos   en   espera  
adelanten  su  ejecución  

104     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

IV.  Arquitecturas  Asíncronas  


Las   arquitecturas   asíncronas   establecen   la   posibilidad   de   hacer   que   algunas   operaciones  
devuelvan   el   control   al   programa   llamante   antes   de   que   hayan   terminado   mientras   siguen  
operando   en   segundo   plano.   Esto   agiliza   el   proceso   de   ejecución   y   en   general   permite  
aumentar  la  escalabilidad  pero  complica  el  razonamiento  sobre  el  programa.  

Modelo  de  Paso  de  ConQnuaciones  


function div(a, b, callback) {
La  función  de  conEnuación  permite  indicar   if (b === 0) callback (Error (...))
a   la   operación   bloqueante   como   debe   else {
proceder   después   de   finalizada   la   var result = a / b;
operación   callback (null, result);
}
}
mul  (2,  3)  

div (8, 2, function (error, data) {


if (error) console.error (error);
div  (3,  4)  
else console.log (data);
});

add  (4,  5)   La  manera  de  proceder  dentro  de  este  modelo  para  establecer  
flujos   de   ejecución   secuenciales   exige   ir   encadenando   cada  
función  subsiguiente  como  conEnuación  de  la  anterior  donde  se  
procesarán  los  resultados.  Esto  conduce  a  una  diagonalización  
2  *  3  /  4  +  5       del  código  incomoda  de  manejar  

105     @javiervelezreye  
Programación  Funcional  en  Node  JS  
Arquitecturas  de  Programación  Funcional  

IV.  Arquitecturas  Asíncronas  


Las   arquitecturas   asíncronas   establecen   la   posibilidad   de   hacer   que   algunas   operaciones  
devuelvan   el   control   al   programa   llamante   antes   de   que   hayan   terminado   mientras   siguen  
operando   en   segundo   plano.   Esto   agiliza   el   proceso   de   ejecución   y   en   general   permite  
aumentar  la  escalabilidad  pero  complica  el  razonamiento  sobre  el  programa.  

Modelo  de  Promesas  


var promise = div (a, b);
L a   p r o m e s a   e s   u n a   m o n a d a   d e   .then (function (data) {
conEnuidad   que   incuye   los   inyectores   de   console.log (data)
conEnuidad   then   y   fail   para   incluir   los   })
manejadores  de  éxito  y  fallo   .fail (function (error) {
console.error (error)
});
div  (3,  4)  
function div (x, y) {
then   var result = ...
fail   return <<toPromise (result)>>;
done   }

Las  promesas  se  convierten  en  un  protocolo  de  comunicación  entre  el  flujo  
llamador   y   llamante.   El   llamante   invoca   la   operación   asíncrona.   Ésta   le  
devuelve  un  objeto  promesa.  El  llamante  inyecta  los  manejadores  de  éxito  
y  fracaso  en  la  promesa.  Y  tras  finalizar,  la  operación  asíncrona  busca  en  la  
promesa  la  función  de  con2nuación  

106     @javiervelezreye  
Programación  Asíncrona  en  Node  JS  
Preguntas  

Mecanismos  
Principios   Técnicas  

Patrones  

Javier  Vélez  Reyes  


 @javiervelezreye  
[email protected]  

107     @javiervelezreye  
Programación  Funcional    
en  NodeJS  
Técnicas,  Patrones  y  Arquitecturas  Funcionales  

Javier  Vélez  Reyes  


 @javiervelezreye  
[email protected]  

Octubre  2014  

También podría gustarte