Programacion Funcional JavaScript PDF
Programacion Funcional JavaScript PDF
Funcional
en
JavaScript
Técnicas,
Patrones
y
Arquitecturas
Funcionales
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
§ 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
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
7
@javiervelezreye
Programación
Funcional
en
JavaScript
Introducción
8
@javiervelezreye
Programación
Funcional
en
JavaScript
Introducción
9
@javiervelezreye
Programación
Funcional
en
JavaScript
Introducción
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
11
@javiervelezreye
Programación
Funcional
en
JavaScript
Introducción
12
@javiervelezreye
Programación
Funcional
en
JavaScript
Introducción
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
14
@javiervelezreye
Programación
Funcional
en
JavaScript
Introducción
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
}
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
}
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
}
Enc
Inm
Par
Com
Abs
}
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
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
Orden
Superior
recursividad
Expresiones
IIFE
Definición
por
casos
Retención
Variables
Clausuras
19
@javiervelezreye
Programación
Funcional
en
JavaScript
JavaScript
como
Lenguaje
Funcional
20
@javiervelezreye
Programación
Funcional
en
JavaScript
JavaScript
como
Lenguaje
Funcional
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
Recursión Indirecta
22
@javiervelezreye
Programación
Funcional
en
JavaScript
JavaScript
como
Lenguaje
Funcional
23
@javiervelezreye
Programación
Funcional
en
JavaScript
JavaScript
como
Lenguaje
Funcional
(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
24
@javiervelezreye
Programación
Funcional
en
JavaScript
JavaScript
como
Lenguaje
Funcional
25
@javiervelezreye
Programación
Funcional
en
JavaScript
JavaScript
como
Lenguaje
Funcional
26
@javiervelezreye
Javier
Vélez
Reyes
@javiervelezreye
§ 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.
28
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
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
30
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
31
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
32
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
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
p,ac >
}
eficiencia
en
memoria
34
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
gg color('cc')('a3')('45')
35
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
36
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
37
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
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
39
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
40
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
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
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
43
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
44
@javiervelezreye
Programación
Funcional
en
JavaScript
Técnicas
de
Programación
Funcional
45
@javiervelezreye
Javier
Vélez
Reyes
@javiervelezreye
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.
47
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
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])
}
49
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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)
}
50
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
Patrón first
52
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
Patrón last
53
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
56
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
Patrón uncurry
57
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
Patrón Qmes
58
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
Patrón maybe
console.log(mbadd(3)); // undefined
console.log(mbadd(2, 3)); // 5
59
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
Patrón around
61
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
62
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
63
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
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
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
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
68
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
69
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
70
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
Patrón tap
71
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
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
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
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
}
75
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
76
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
77
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
78
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
80
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
81
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
82
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
84
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
1
Programación
Asíncrona
en
NodeJS.
En
Slideshare@
jvelez77
85
@javiervelezreye
Javier
Vélez
Reyes
@javiervelezreye
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
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.
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.
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.
90
@javiervelezreye
Programación
Funcional
en
Node
JS
Arquitecturas
de
Programación
Funcional
91
@javiervelezreye
Programación
Funcional
en
Node
JS
Arquitecturas
de
Programación
Funcional
92
@javiervelezreye
Programación
Funcional
en
Node
JS
Arquitecturas
de
Programación
Funcional
93
@javiervelezreye
Programación
Funcional
en
Node
JS
Arquitecturas
de
Programación
Funcional
94
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
96
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
97
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
98
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
99
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
100
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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, ...
101
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
102
@javiervelezreye
Programación
Funcional
en
JavaScript
Patrones
de
Diseño
Funcional
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
104
@javiervelezreye
Programación
Funcional
en
Node
JS
Arquitecturas
de
Programación
Funcional
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
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
107
@javiervelezreye
Programación
Funcional
en
NodeJS
Técnicas,
Patrones
y
Arquitecturas
Funcionales
Octubre 2014