Programación Funcional en JavaScript

Click here to load reader

  • date post

    08-Jul-2015
  • Category

    Technology

  • view

    2.953
  • download

    2

Embed Size (px)

description

Programación Funcional en Javascript. 27/10/2014. NodeJS Madrid Video: http://bit.ly/1xTizFc Code: http://bit.ly/1qmmR3Q La programación funcional está cogiendo fuerte tracción en los últimos años dentro de la comunidad de desarrollo. Tal vez ello se deba al surgimiento de nuevas arquitecturas que demandan cotas de escalabilidad, resistencia y flexibilidad en el marco de soluciones centradas en procesos de transformación. Pero más allá de una simple moda, como trataremos de mostrar en esta charla, la programación funcional conduce a soluciones de código robustas, versátiles y expresivas que difícilmente son comparables con las propias de la orientación a objetos. Además JavaScript, como la mayoría de los lenguajes de scripting es un lenguaje idiomático que invita a pensar en términos funcionales. De hecho muchas veces, cuando programamos en Javascript, desarrollamos soluciones funcionales casi sin darnos cuenta. Pero para trabajar correctamente en el marco de este paradigma debemos saber, qué es exactamente la programación funcional, cuáles son sus ventajas y principios fundacionales, de qué mecanismos se sirve, qué técnicas de programación se utilizan, qué patrones de diseño funcional existen a nuestra disposición y qué estilos arquitectónicos emergen. En esta charla descubriremos cómo se construyen arquitecturas funcionales dirigidas por los datos, hablaremos de programación por capas basada en orden superior y presentaremos modelos de programación concomitantes como la programación reactiva basada en streams o las arquitecturas map/reduce propias de las técnicas de big data.

Transcript of Programación Funcional en JavaScript

  • Javier Vlez Reyes @javiervelezreye

    [email protected]

    Tcnicas, Patrones y Arquitecturas Funcionales

    Programacin Funcional en JavaScript

    Octubre 2014

  • @javiervelezreye 2

    Presentacin Programacin Funcional en JavaScript

    Licenciado en inform2ca por la Universidad Politcnica de Madrid (UPM) desde el ao 2001 y doctor en inform2ca por la Universidad Nacional de Educacin a Distancia (UNED) desde el ao 2009, Javier es inves2gador y est especializado en el diseo y anlisis de la colaboracin. Esta labor la compagina con ac2vidades de evangelizacin, consultora, mentoring y formacin especializada para empresas dentro del sector IT. Inquieto, vido lector y seguidor cercano de las innovaciones en tecnologa.

    I. Quin Soy?

    II. A Qu Me Dedico? Desarrollado Front/Back

    Evangelizacin Web Arquitectura SoVware

    Formacin & Consultora IT E-learning

    Diseo de Sistemas de Colaboracin Learning Analy2cs

    Gamicacin Colabora2va

    [email protected]

    @javiervelezreye

    linkedin.com/in/javiervelezreyes

    gplus.to/javiervelezreyes

    jvelez77

    javiervelezreyes

    youtube.com/user/javiervelezreyes

  • Javier Vlez Reyes @javiervelezreye

    [email protected]

    1 Introduccin Introduccin Obje2vos de la Programacin Funcional Principios de Diseo Funcional Dimensiones y Planos de Ac2vidad

    Introd

    uccin

    Prog

    ramac

    in Fu

    nciona

    l en Java

    Scrip

    t

  • @javiervelezreye 4

    Introduccin Programacin Funcional en JavaScript

    La programacin funcional es un viejo conocido dentro del mundo del desarrollo. No obstante, en los l2mos aos est cogiendo traccin 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 diseo funcional. En este texto revisaremos sus obje2vos y principios y discu2remos los mecanismos, tcnicas y patrones empleados actualmente para construir arquitecturas funcionales haciendo uso de JavaScript.

    I. Introduccin

    Programacin Funcional

    Programacin Orientada a Objetos

    Arquitecturas centradas en la transformacin

    Variantes funcionales

    Transparencia Referencial

    Inmutabilidad

    ComposiEvidad

    Puntos de Extensin Polimrca Arquitecturas

    centradas en la abstracciones SusEtuEvidad

    Liskoviana Encapsulacin de

    estado Arquitecturas

    dirigidas por ujos de control

    Arquitecturas dirigidas por ujos de

    datos

  • @javiervelezreye 5

    Introduccin Programacin Funcional en JavaScript

    A. Especicacin DeclaraQva

    II. ObjeQvos de la Programacin Funcional

    La programacin funcional persigue disear especicaciones de comportamiento abstracto que se centren en la descripcin de las caracters2cas de un problema ms que en una forma par2cular de resolverlo. De acuerdo a esto, se en2ende que la responsabilidad de encontrar una solucin para el problema descansa no tanto en manos del programador sino en la arquitectura funcional subyacente que toma en cuenta dicha especicacin.

    Qu

    Cmo

    function total (type) { return basket.filter (function (e) { return e.type === type; }).reduce (function (ac, e) { return ac + e.amount * e.price; }, 0); }

    function total (type) { var result = 0; for (var idx = 0; idx < basket.length; idx++) { var item = basket[idx]; if (basket[idx].type === type) result += item.amount * item.price; } return result; }

    var basket = [ { product: 'oranges', type:'food', amount: 2, price:15 }, { 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 } ];

    La descripcin uida del esElo funcional permite entender fcil-mente la especicacin

    Aunque operaEvamente es equivalente, el esElo imperaEvo es ms confuso y resulta ms diRcil de entender

    Objetos

    Funcional

  • @javiervelezreye 6

    Introduccin Programacin Funcional en JavaScript

    B. Abstraccin Funcional

    II. ObjeQvos de la Programacin Funcional

    La programacin funcional persigue alcanzar una especicacin de alto nivel que capture esquemas algortmicos de aplicacin transversal. Como veremos a con2nuacin, as se fomenta la reu2lizacin y la adaptacin idiom2ca. Esto se consigue con arquitecturas centradas en la variabilidad funcional y contrasta ortogonalmente con la orientacin a objetos.

    var vehicles = [new Car(), new Truck(), ...]; var garage = function (vehicles) { for (v in vehicles) vehicles[v].test(); }; garage(vehicles);

    var phases = [ function body (v) {...}, function paint (v) {...} ]; var test = function (phases) { function (vehicle) { return phases.reduce(function (ac, fn) { return fn(ac); }, vehicle); } };

    Abstraccin Funcional

    Abstraccin de Qpos Objetos

    Funcional

    V1 V2 V3

    Car Truck

    Bike

    vehicles

    body

    paint

    v

    En FP la funcin es la unidad de abstraccin ya que permite denir esquemas algortmicos que dependen de funciones pasadas como parmetros

    En OOP los algoritmos se distribuyen entre objetos con implemen-taciones variantes

  • @javiervelezreye 7

    Introduccin Programacin Funcional en JavaScript

    C. ReuQlizacin Funcional

    II. ObjeQvos de la Programacin Funcional

    Como consecuencia de la capacidad de abstraccin en la especicacin declara2va, la programacin funcional alcanza cotas elevadas en la reu2lizacin de funciones. Este nivel de reu2lizacin algortmica no se consigue en otros paradigmas como en la orientacin a objetos.

    El esquema algortmico se reuEliza sobre disEntas estructuras de datos y con disEntas aplicaciones funcionales

    var users = [ { name: 'jvelez', sex: 'M', age: 35 }, { name: 'eperez', sex: 'F', age: 15 }, { name: 'jlopez', sex: 'M', age: 26 } ]; var adult = function (u) { return u.age > 18; }; var name = function (ac, u) { ac.push(u.name); return ac; }; get(users)(adult, name, []);

    var get = function (collection) { return function (filter, reducer, base) { return collection .filter(filter) .reduce(reducer, base); }; };

    var basket = [ { product: 'oranges', type: 'F', price:15 }, { product: 'bleach' , type: 'H', price:15 }, { product: 'pears' , type: 'F', price:45 }, ]; var food = function (p) { return p.type === 'F'; }; var total = function (ac, p) { return ac + p.price; }; get(basket)(food, total, 0);

  • @javiervelezreye 8

    Introduccin Programacin Funcional en JavaScript

    D. Adaptacin Funcional

    II. ObjeQvos de la Programacin Funcional

    Una de las virtudes de la programacin funcional es la capacidad de poder transformar la morfologa de las funciones para adaptarlas a cada escenario de aplicacin real. En trminos concretos esto signica poder cambiar la signatura de la funcin y en especial la forma en que se proporcionan los parmetros de entrada y resultados de salida. Veremos que existen mecanismos tcnicas y patrones para ar2cular este proceso.

    function greater (x, y) { return x > y; }

    function greater (x, y) { return y > x; }

    reverse

    (function greater (x) { function (y) { return y > x; } })(18)

    function greater (x) { function (y) { return y > x; } }

    curry

    parQal

    Se invierte el orden de aplica-cin de los parmetros de forma transparente

    Se transforma la evaluacin de la funcin para que pueda ser evaluada por fases

    Se congura parcialmente la funcin para obtener el predicado de adulto

  • @javiervelezreye 9

    Introduccin Programacin Funcional en JavaScript

    E. Dinamicidad Funcional

    II. ObjeQvos de la Programacin Funcional

    La programacin funcional permite disear funciones que sean capaces de construir abstracciones funcionales de forma dinmica en respuesta a la demanda del contexto de aplicacin. Como veremos, este obje2vo se apoya en mecanismos de abstraccin y tambin abunda en la adaptacin funcional que acabamos de describir.

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

    function greater (x) { return function (y) { return y > x; } }

    Se demanda un predicado funcional que discrimine a los jubilados

    Se demanda un predicado funcional que discrimine a los adultos

    Se demanda un predicado funcional que discrimine a los jvenes

    La funcin greater es una factora funcional que dene comporta-mientos dinamicamente

    Proveedor

    Clientes

    var isOld = greater(65) var isYoung = greater(25)

    var isAdult = greater(25)

  • @javiervelezreye 10

    Introduccin Programacin Funcional en JavaScript

    A. Principio de Transparencia Referencial

    III. Principios de Diseo Funcional

    El principio de transparencia referencial predica que en toda especicacin funcional correcta, cualquier funcin debe poder subs2tuirse en cualquier mbito de aplicacin por su expresin funcional sin que ello afecte al resultado obtenido. La interpretacin de este principio de diseo 2ene tres lecturas complementarias.

    Funciones Puras

    Dado que el predicado greater slo depende de sus parmetros de entrada x e y, se trata de una funcin pura. Por ello, manEene la transparencia referencial permiEendo su susEtucin sin impacto en la semnEca del contexto de aplicacin

    var old = greater(65)

    var old = (function greater (x) { function (y) { return y > x; } })(65);

    Se dice que una funcin es pura recuerda al es2lo de comportamiento matem2co si su valor de retorno slo depende de los parmetros de entrada y no del estado ambiental (variables globales, variables retenidas en mbito lxico, operaciones de E/S, etc.).

    f Estado

  • @javiervelezreye 11

    Introduccin Programacin Funcional en JavaScript

    A. Principio de Transparencia Referencial

    III. Principios de Diseo Funcional

    El principio de transparencia referencial predica que en toda especicacin funcional correcta, cualquier funcin debe poder subs2tuirse en cualquier mbito de aplicacin por su expresin funcional sin que ello afecte al resultado obtenido. La interpretacin de este principio de diseo 2ene tres lecturas complementarias.

    Comportamiento Idempotente

    pop + pop === 2 * pop

    Se dice que una funcin es idempotente si siempre devuelve el mismo resultado para los mismos parmetros de entrada. En nuestro ejemplo debera vericarse esta igualdad:

    function Stack () { var items = []; return { push: function (e) { items.push(e); }, pop: function () { return items.pop(); } }; }

    function Stack () { return { stack: [] }; } function push (s, e) { return { stack: s.stack.concat(e), top: e }; } function pop (s) { var stack = [].concat(s.stack); var e = stack.pop(); return { stack: stack, top: e }; }

    EsQlo Orientado a Objetos

    EsQlo Funcional La pila manEene el estado interno y las operaciones push y pop no resultan idempotentes

    El estado se manEene externa-mente y se pasa como parmetro a cada operacin con lo que el comportamiento es idempotente

  • @javiervelezreye 12

    Introduccin Programacin Funcional en JavaScript

    A. Principio de Transparencia Referencial

    III. Principios de Diseo Funcional

    El principio de transparencia referencial predica que en toda especicacin funcional correcta, cualquier funcin debe poder subs2tuirse en cualquier mbito de aplicacin por su expresin funcional sin que ello afecte al resultado obtenido. La interpretacin de este principio de diseo 2ene tres lecturas complementarias.

    AgnosQcismo de Estado

    La entrada acumula toda la informacin ambiental en forma de estado

    clean

    words

    count

    Entrada

    Salida

    Fronteras Arquitectnicas

    Dentro de la arquitectura el estado es acarreado como parmetro a lo largo de la cadena de transformacin

    Cada abstraccin en el mbito arquitec-tnico es una funcin pura que hace depender su salida exclusivamente de sus parmetros de entrada

    Todo problema de aplicacin real se caracteriza por un estado intrnseco. El agnos2cismo de estado no niega esta realidad. En su lugar, el principio debe interpretarse como que dentro de las fronteras del sistema el comportamiento funcional slo puede depender de los parmetros explcitamente denidos en cada funcin.

  • @javiervelezreye 13

    Introduccin Programacin Funcional en JavaScript

    B. Principio de Inmutabilidad de Datos

    III. Principios de Diseo Funcional

    En el modelo de programacin impera2va, la opera2va de computo se en2ende como un proceso secuencial y paula2no de transformacin del estado mantenido por la arquitectura hardware de la mquina. En programacin 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 informacin no existe.

    var x = 1 ... x = x + 1

    [email protected](0) = 1 ... [email protected](t+1) = [email protected](t) + 1

    En programacin imperaEva las variables se enEenden como depsitos de informacin en memoria que pueden actualizarse durante el Eempo de vida del programa. La dimensin Eempo queda oculta y esto diculta el razonamiento

    La programacin funcional pone estrs en que los cambios en los datos de un programa deben manifestarse como funciones sobre la dimensin Eempo. Esto signica que el concepto de variables como deposito de informacin y las operaciones de actualizacin sobre ellas no estn permiEdas

    ImperaQvo P. Funcional

    En trminos prc2cos la aplicacin se este principio se traduce en que las funciones nunca deben actualizar los parmetros de entrada sino generar a par2r de ellos resultados de salida

    function push (s, e) { return s.push(e); } function push(s, e) { return s.concat(e); }

    Se modica s

    No se modica s

    EsQlo ImperaQvo

    EsQlo Funcional

  • @javiervelezreye 14

    Introduccin Programacin Funcional en JavaScript

    C. Principio de Computacin Centrada en Colecciones

    III. Principios de Diseo Funcional

    A diferencia de lo que ocurre en otros paradigmas como en orientacin a objetos donde los datos se organizan en forma de grafos relacionales, en programacin 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 computacin de la programacin funcional est centrado en colecciones.

    Set Un conjunto se modela como un array o un diccionario de booleanos

    1 3 4

    [true, false, true, true]

    Bag Una bolsa se modela como un un diccionario de contadores

    a b

    c

    {a: 2, b: 3, c: 1}

    a b b

    Binary Tree Un array se aplana como una coleccin anidada de arrays de 3 posiciones, rbol izquierdo, nodo, rbol derecho

    1

    5 2

    Heap Una cola con prioridad es un diccionario de arrays o un array de arrays

    {1: [a, c], 2: [b, c, d], 3: [f]}

    7 6 4 3

    [ [ [[],3,[]], 2, [[],4,[]]], 1, [[[],6,[]], 5, [[],7,[]]] ]

    a c b d e f

    1 2 3 [

    [a, c], [b, c, d], [f] ]

    1 Los diccionarios son una aproximacin de representacin aceptable en tanto que pueden procesarse como colecciones de pares clave-valor

  • @javiervelezreye 15

    Introduccin Programacin Funcional en JavaScript

    D. Principio de Diseo Dirigido por Capas

    III. Principios de Diseo Funcional

    La construccin de arquitecturas funcionales sigue un proceso de diseo dirigido por capas o niveles de especicacin. Desde las abstracciones ms generales encontradas en libreras funcionales se construye un nivel idiom2co que propone un esquema abstracto de solucin para el problema propuesto y slo entonces se concreta en el dominio par2cular del problema.

    var users = [{ name: 'jlopez', sex: 'M', age: 26 } ...]; var male = function (u) { return u.age > 18; }; var name = function (ac, u) { ac.push(u.name); return ac; }; get(users)(male, name, []);

    var get = function (collection) { return function (filter, reducer, base) { return collection .filter(filter) .reduce(reducer, base); }; };

    map reduce filter ...

    Nivel de Dominio Se contextualiza el esquema anterior dentro del dominio de aplicacin concretando con datos y funciones especcas

    Nivel IdiomQco Se crea un esquema funcional que resuelve la familia de problemas al que pertenece el problema planteado

    Nivel de Librera Se uElizan funciones generales con un alto nivel de abstraccin

    Nivel de Ab

    straccin

    ReuQlizacin Transversal a Dominio

  • @javiervelezreye 16

    Introduccin Programacin Funcional en JavaScript

    A. Ejes Dimensionales

    IV. Caracterizacin de la Programacin Funcional

    A lo largo de esta introduccin hemos presentado el paradigma de programacin funcional centrndonos 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 sern cubiertos en el siguiente captulo.

    Principios

    Mecanismos

    Abs

    Reut

    Dec

    Adap

    ObjeQvos

    Los objeEvos describen las caractersEcas diferenciales de la programacin funcional y jusEcan sus procesos de desarrollo en relacin a otros paradigmas

    Por qu?

    Los principios de diseo ofrecen lneas maestras que dirigen los procesos de desarrollo funcional

    Cmo?

    Los mecanismos conforman las herramientas del lenguaje para arEcular los desarrollos funcionales

    Con qu?

    Tran Inmut

    Enc

    Par

    Inm

    Com

    Abs

    Dina

    Capas Captulo 1

    }

    }

    Captulo 2 }

    Captulo 1

  • @javiervelezreye 17

    Introduccin Programacin Funcional en JavaScript

    B. Planos de AcQvidad

    IV. Caracterizacin de la Programacin Funcional

    El recorrido de este texto avanza describiendo cada uno de los tres planos de ac2vidad que caracterizan la programacin funcional. En el captulo 3 abordaremos las tcnicas de programacin esenciales del paradigma. El captulo 4 profundiza en los patrones de diseo funcionales. Y el captulo 5 presenta las principales arquitecturas en programacin funcional.

    Principios

    Mecanismos

    ObjeQvos

    Los esElos arquitectnicos propor-cionan restricciones estructurales que determinan formas cannicas de abordar familias especcas de problemas

    Arquitecturas Funcionales

    El diseo establece formas cannicas de aplicabilidad probada para dar respuesta a problemas recurrentes

    Patrones de Diseo

    Las tcnicas indican cmo aplicar los mecanismos del lenguaje en el proceso de programacin funcional

    Tcnicas de Programacin

    Patrones

    Diseadores

    Arquitectos

    Plano Tecnolgico

    Programadores

    Abs

    Reut

    Adap

    Enc

    Par

    Inm

    Com

    Abs

    Dina

    Tran Inmut

    Capas

    }

    Captulo 5

    Captulo 3 }

    Captulo 4 }

  • Javier Vlez Reyes @javiervelezreye

    [email protected]

    2 JavaScript como Lenguaje Funcional Denicin Funcional por Casos Denicin por Recursin Expresiones Funcionales de Invocacin Inmediata IIFE Denicin en Orden Superior Clausuras & Retencin de Variables Ja

    vaScrip

    t com

    o Le

    ngua

    je Fun

    cion

    al

    Prog

    ramac

    in Fu

    nciona

    l en Java

    Scrip

    t

  • @javiervelezreye 19

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    Como ya hemos comentado, los procesos de programacin funcional consisten esencialmente en la denicin de una coleccin de declaraciones funcionales que puedan adaptarse a dis2ntos niveles de abstraccin y aplicarse conjugadamente para resolver problemas de forma declara2va. Para ar2cular estas tareas de denicin el paradigma funcional ofrece una coleccin de mecanismos esenciales que revisamos en este captulo.

    I. Introduccin

    Tcnicas PF

    Patrones PF

    El nivel de lenguaje est formado por la coleccin de mecanismos de programacin que proporciona el lenguaje de forma naEva

    Nivel de Lenguaje

    Las deciencias que por su concepcin presenta el lenguaje se deben suplir a este nivel por aplicacin de tcnicas y patrones de diseo que revisaremos en prximos captulos

    Nivel IdiomQco App App App

    Den

    icin po

    r casos

    recursividad

    Expresione

    s IIFE

    Orden

    Sup

    erior

    Clau

    suras

    Retencin Variables

    Sobrecarga Fun

    cion

    al

    Den

    icin po

    r Patrone

    s

    JS Funcional

  • @javiervelezreye 20

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    A. Denicin Funcional por Casos

    II. Mecanismos de Programacin Funcional

    La forma ms sencilla de denir una funcin es diseando explcitamente la coleccin de valores de retorno que debe devolver para cada posible parmetro de entrada. Aunque este mecanismo parece poco exible aisladamente, cuando se conjuga con otras formas de denicin resulta de aplicacin frecuente.

    La denicin por casos se expresa declarando explcitamente el valor que debe devolver la funcin para cada posible valor de los parmetros de entrada

    function f (parmetros) { return caso-1 ? resultado-1 : caso-2 ? resultado-2 : resultado-defecto; }

    El uso anidado del operador condicional permite expresar los pares caso-resultado como una nica expresin de retorno

    nica Expresin

    Enumeracin Explcita de casos

    function comparator(x) { return x > 0 ? 1 : x === 0 ? 0 : -1 ; }

    function even(n) { return n % 2; }

    Se uEliza el operador condicional anidado para denir cada caso funcional

    La denicin mediante una nica expresin es el escenario ms sencillo de denicin por casos

  • @javiervelezreye 21

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    B. Denicin por Recursin

    II. Mecanismos de Programacin Funcional

    La denicin de funciones por recursin consiste en la invocacin de la propia funcin como parte del proceso de denicin. El esquema de denicin recursivo se apoya en el mecanismo anterior para dis2nguir entre casos base aqullos que devuelven un resultado nal de aqullos casos recursivos donde el valor de retorno vuelve a invocar a la propia funcin.

    function f (parmetros) { return caso-base-1 ? resultado-base-1 : caso-base-2 ? resultado-base-2 : caso-recursivo-1 ? resultado-recursivo-1 : caso-recursivo-2 ? resultado-recursivo-2 : resultado-defecto ; }

    Los casos base son el nal del proceso recursivo y se suponen soluciones inmediatas a problemas sencillos

    Casos base Los casos recursivos se disean invocando a la propia funcin sobre valores de parmetros que convergen a los casos base

    Casos recursivos

    Asegrese de que cada resultado recursivo converge a alguno de los casos base

    II. Regla de convergencia I. Regla de cobertura Asegrese de que todos los casos base del problema han sido incluidos explcitamente en la denicin de la funcin

    Para disear cada caso recursivo asuma que la funcin por denir est ya den ida para va lo res de parmetros ms prximos a los casos base

    III. Regla de autodenicin

  • @javiervelezreye 22

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    B. Denicin por Recursin

    II. Mecanismos de Programacin Funcional

    En funcin de cmo se expresan los casos recursivos de una funcin podemos dis2nguir entre dos 2pos de situaciones. En la recursin directa, los casos recursivos de la funcin se expresan en trminos de llamadas a ella misma. En la recursin indirecta, la funcin invoca a otra funcin que recurre sobre la primera.

    Recursin Directa

    function factorial (n) { return n === 0 ? 1 : n * factorial(n - 1); }

    factorial(4) = 4 * factorial(3) = 4 * 3 * factorial(2) = 4 * 3 * 2 * factorial(1) = 4 * 3 * 2 * 1 * factorial(0) = 4 * 3 * 2 * 1 * 1 = 24

    Recursin Indirecta

    function even (n) { return n === 0 ? true : !odd(n-1); } function odd (n) { return n === 0 ? false : !even(n-1); }

    even(4) = !odd(3) = !!even(2) = !!!odd(1) = !!!!even(0) = !!!!true = true

    Los casos recursivos convergen hacia los casos base reduciendo el tamao del problema en una unidad a cada paso

    La convergencia hacia los casos base va incluyendo un operador de negacin que se resuelven al llegar al caso base

  • @javiervelezreye 23

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    B. Denicin por Recursin

    II. Mecanismos de Programacin Funcional

    Dado que la programacin funcional no dispone de estructuras de control de ujo, la nica forma de resolver problemas que requieren un computo itera2vo es expresarlas a par2r de una formulacin recursiva. Aunque puede resultar en principio ms complejo, la expresividad funcional aumenta con este 2po de expresiones. Adems hay problemas que 2enen una resolucin inherentemente recursiva.

    Problema de las Torres de Hanoi

    Mover discos de uno en uno para dejarlos en la misma posicin de A en C usando B como auxiliar. Los discos por encima de uno dado deben ser siempre de menor tamao que ste.

    function hanoi (n, origen, aux, destino) { if (n === 1) mover(origen, destino); else { hanoi(n-1, origen, destino, aux); mover(origen, destino); hanoi(n-1, aux, origen, destino); } } function mover (origen, destino) { destino.push (origen.pop()); } var A = [4, 3, 2, 1], B = [], C = [] hanoi(A, B, C);

    A B C

    n-1

    1

    n-1

    1

    2

    3

  • @javiervelezreye 24

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    C. Expresiones Funcionales e Invocacin Inmediata

    II. Mecanismos de Programacin Funcional

    No en pocas ocasiones la necesidad de denir una funcin se restringe a un solo uso que se realiza a con2nuacin de su denicin. Si encerramos una denicin de funcin entre parntesis y aplicamos a la expresin resultante el operador de invocacin los parmetros actuales a su vez entre parentesis y separados por comas obtenemos una expresin funcional de invocacin inmediata IIFE.

    (function f (parmetros-formales) { })(parmetros-actuales);

    La expresin funcional se invoca directamente por aplicacin de los parmetros actuales

    La denicin funcional se encierra entre parntesis para converErla en una expresin evaluable

    Expresin Funcional Invocacin Inmediata

    var cfg = (function config(user) { // getting config from DB return {...} })('jvelez');

    Un cpico ejemplo de IIFE se da cuando se pretenden realizar clculos complejos o tareas que se efectuarn una sola vez a lo largo del cdigo

    La ventaja de este Epo de construcciones es que la funcin se libera de la memoria tras su ejecucin

  • @javiervelezreye 25

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    D. Denicin en Orden Superior

    II. Mecanismos de Programacin Funcional

    En JavaScript las funciones son ciudadanos de primer orden. Esto quiere decir que a todos los efectos no existe ningn 2po de diferencia entre una funcin y cualquier valor de otro 2po primi2vo. Esto permite a una funcin recibir otras funciones como parmetros o devolver funciones como retorno. Este mecanismo se le conoce con el nombre de orden superior.

    Funciones como Parmetros a Otras Funciones

    El paso de funciones como parmetros a una funcin permite que el comportamiento de sta sea adaptada por medio de la inyeccin de cdigo variante en cada invocacin. Esta aproximacin contrasta con la programacin por 2pos variantes propia de la orientacin a objetos.

    Funciones como Retorno de Otras Funciones

    Las funciones son capaces de generar dinmicamente funciones que devuelven como resultado. Esto es de especial inters cuando la funcin devuelta es el resultado de transformar una funcin recibida como argumento. Este proceso jus2ca el nombre de orden superior ya que se opera con funciones genricas.

    function once (fn) { var called = false; return function () { if (!called) { called = true; return fn.apply(this, arguments); } } }

    var greater = function (x, y) {...}; var less = function (x, y) {...}; var even = function (x) {...}; [1, 4, 3, 2].sort(greater); [1, 4, 3, 2].sort(less); [1, 4, 3, 2].filter(even);

  • @javiervelezreye 26

    JavaScript como Lenguaje Funcional Programacin Funcional en JavaScript

    E. Clausuras & Retencin de Variables

    II. Mecanismos de Programacin Funcional

    Las funciones que, por medio de los mecanismos de orden superior, devuelven funciones como resultado se pueden expresar en trminos de variables locales o parmetros presentes en el entorno funcional donde se denen. La retencin de variables es el mecanismo mediante el cual dichas variables y parmetros son mantenidos durante todo el 2empo de vida de la funcin de retorno. Este 2po de funciones se denominan clausuras.

    function Logger(cls) { var pre = 'Logger'; var post = '...'; return function (message) { console.log ('%s[%s] - [%s]%s', pre, cls, message, post); } }

    var log = Logger('My Script'); Log('starting'); log(1234); log('end');

    function (message) {...}

    pre post cls

    Clausura

    Las clausuras son un mecanismos de construccin funcional que captura de forma permanente un estado de conguracin que condiciona su comportamiento

    Variables Retenidas Al extraer una funcin fuera de su mbito lxico de denicin se manEene el contexto de variables y parmetros que dicha funcin uEliza.

  • Javier Vlez Reyes @javiervelezreye

    [email protected]

    3 Tcnicas de Programacin Funcional Abstraccin Encapsulacin Inmersin por Recursin y Acumulacin Evaluacin Parcial Composicin Funcional & Composicin Mondica T

    cnicas

    de Prog

    ramac

    in Fu

    nciona

    l

    Prog

    ramac

    in Fu

    nciona

    l en Java

    Scrip

    t

  • @javiervelezreye 28

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    A par2r de los mecanismos que ofrece JavaScript como lenguaje de programacin se puede escribir soVware bien centrado en el paradigma funcional. No obstante, para ello es necesario conocer una coleccin de tcnicas bsicas que describen formas cannicas de hacer frente a problemas recurrentes. A lo largo de este captulo haremos una revisin de las tcnicas ms relevantes.

    I. Introduccin

    Las tcnicas de abstraccin permiten denir especicaciones funcionales con diferentes grados de generalidad y reu2lizacin transversal

    Abstraccin En funcional la encapsulacin de estado es un mal a veces necesario y en muchas ocasiones puede reemplazarse por encapsulacin de comportamiento

    Encapsulacin Las tcnicas de inmersin son una con-jugacin de abstraccin, encapsulacin y recursividad para obtener control de ujo dirigido por datos

    Inmersin

    La evaluacin parcial permite evaluar una funcin en varias fases reduciendo paula2namente el nmero de variables libres

    Evaluacin Parcial La composicin funcional permite ar2cular procesos de secuenciamiento de funciones denidas como expresiones anal2cas

    Composicin Funcional La transformacin mondica persigue adaptar funciones para conver2rlas en transformaciones puras que soporten procesos de composicin

    Transformacin Mondica

    La inversin de control permite permutar entre las arquitecturas funcionales centradas en los datos y las centradas en las transformaciones

    Inversin de Control

  • @javiervelezreye 29

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    A. Tcnicas de Abstraccin

    II. Tcnicas de Programacin Funcional

    Una de las tcnica de programacin funcional ms comnmente u2lizadas, en alineamiento con los principios de diseo presentados anteriormente, es la abstraccin funcional. Las tareas de abstraccin deben entenderse como un proceso de transformacin en el que la denicin de una funcin se reexpresa en trminos ms generales para dar cobertura a un abanico ms amplio de escenarios de aplicacin. Podemos dis2nguir tres dimensiones de abstraccin.

    Abstraccin en Anchura

    Suma convencional de dos n-meros pasados como para-metros

    add(x, y)

    add

    Combina mediante la funcin c todos los parmetros a parEr de uno dado en posicin p

    reduceFrom(p, c)(x, y, )

    reduceFrom

    Suma todos los parmetros de la funcin independientemente de la aridad

    addAll(x, y, z, )

    addAll

    Suma todos los parmetros de la funcin a parEr de aqul que ocupa una posicin p

    add(p)(x, y, z, )

    addFrom Abstraccin en Comportamiento

    Abstraccin en Alcance

  • @javiervelezreye 30

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    B. Tcnicas de Encapsulacin

    II. Tcnicas de Programacin Funcional

    Mediante el uso de clausuras y la retencin de variables es posible capturar, durante la fase de diseo o ejecucin, cierta informacin que resulta de u2lidad para adaptar el comportamiento de la funcin a lo largo del 2empo. Es posible dis2nguir entre encapsulacin de estado y de comportamiento.

    Encapsulacin de Estado. Pila Undo

    function Stack () { var items = []; var history = []; return { push: function (e) { history.push([].concat(items)); items.push(e); }, pop: function () { history.push([].concat(items)); return items.pop(); }, undo: function () { if (history.length > 0) items = history.pop(); } }; }

    Las variables que capturan el estado quedan retenidas dentro de la clausura lo que permite arEcular modelos de programacin funcional que evolucionan con el Eempo

    Retencin de Estado

    Ojo! Las funciones que dependen del estado son en realidad una mala prcEca de programacin de acuerdo a los principios de diseo del paradigma

    Dependencia de Estado

    1

    2

    3

    1

    1 2

    2 31

    items history

    undo

  • @javiervelezreye 31

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    B. Tcnicas de Encapsulacin

    II. Tcnicas de Programacin Funcional

    Mediante el uso de clausuras y la retencin de variables es posible capturar, durante la fase de diseo o ejecucin, cierta informacin que resulta de u2lidad para adaptar el comportamiento de la funcin a lo largo del 2empo. Es posible dis2nguir entre encapsulacin de estado y de comportamiento.

    Encapsulacin de Comportamiento. Pila Undo function Stack () { var items = []; var history = []; return { push: function push (e) { history.push(function(){items.pop()}); items.push(e); }, pop: function pop () { var e = items.pop(); history.push(function(){items.push(e);}); return e; }, undo: function undo() { if (history.length > 0) history.pop()(), } }; }

    Dentro de cada operacin, se registran en el histrico las operaciones inversas para luego invocarlas desde la operacin deshacer

    En este caso la variable de histrico captura la coleccin de operaciones inversas que permiten deshacer las transacciones segn han ido sucediendo

    Retencin de Comportamiento

    Operaciones Inversas

    1

    2

    3

    pop

    items history

    undo pop pop

    pop pop pop

  • @javiervelezreye 32

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    B. Tcnicas de Encapsulacin

    II. Tcnicas de Programacin Funcional

    Mediante el uso de clausuras y la retencin de variables es posible capturar, durante la fase de diseo o ejecucin, cierta informacin que resulta de u2lidad para adaptar el comportamiento de la funcin a lo largo del 2empo. Es posible dis2nguir entre encapsulacin de estado y de comportamiento.

    Encapsulacin de Comportamiento. Bus

    function Bus () { var fns = {}; return { receive: function (e, fn) { fns[e] = fn; }, send: function (e, ctx) { return fns[e].apply(null, ctx); } }; } var bus = Bus(); bus.receive('add', function (x,y) {return x+y;}); bus.receive('sub', function (x,y) {return x-y;}); bus.send('add', [3,2]); bus.send('sub', [7,3]);

    bus

    fn

    sub x - y

    x + y add

    event

    El productor emite con la operacin send un evento a los receptores

    send

    send('add', [3,2])

    El consumidor se r eg i s t r a en l o s eventos de inters

    receive receive('add', +)

    3+2

  • @javiervelezreye 33

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    C. Diseo por Inmersin

    II. Tcnicas de Programacin Funcional

    Dado que la programacin funcional no soporta los esquemas itera2vos propios de la programacin impera2va, es preciso orientar los clculos a la recurrencia apoyndose para ello en parmetros auxiliares. Las tcnicas de inmersin conjugan encapsulacin y abstraccin con el uso de parmetros auxiliares. Podemos dis2nguir diferentes 2pos de inmersin.

    function find (v, e) { var aux = function (v, e, p) { return (p > v.length) ? -1 : (v[p] === e) ? p : aux(v, e, p + 1); }; return aux(v, e, 0); }

    I. Inmersin por Recorrido

    function addAll (v) { return (function aux(v, p) { if (p === v.length-1) return v[p]; else return v[p] + aux (v, p+1); }) (v, 0); }

    La inmersin de recorrido exEende la funcin introduciendo un nuevo parmetro cuyo propsito es llevar la cuenta del punto hasta el que se ha avanzado en el vector.

    aux([1,2,3], 0) = 1 + aux([1,2,3], 1) = 1 + 2 + aux ([1,2,3], 2) = 1 + 2 + 3 = 6

    La tcnica se apoya es una abstraccin que queda sumergida dentro de la ms especca por encapsulacin

    321

    p >

  • @javiervelezreye 34

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    C. Diseo por Inmersin

    II. Tcnicas de Programacin Funcional

    Dado que la programacin funcional no soporta los esquemas itera2vos propios de la programacin impera2va, es preciso orientar los clculos a la recurrencia apoyndose para ello en parmetros auxiliares. Las tcnicas de inmersin conjugan encapsulacin y abstraccin con el uso de parmetros auxiliares. Podemos dis2nguir diferentes 2pos de inmersin.

    II. Inmersin por Acumulacin

    La acumulacin se aplica aqu para obtener recursi-vidad nal buscando la eciencia en memoria

    321

    p,ac

    >

    function addAll (v) { return (function aux(v, p, ac) { if (p === v.length) return ac; else return aux (v, p+1, v[p]+ac); })(v, 0, 0); }

    function even (v) { return (function aux(v, p, ac){ if (p === v.length) return ac; else { if (v[p] % 2 === 0) ac.push(v[p]); return aux(v, p+1, ac); } })(v, 0, []); }

    Se uEliza la tcnica de acumulacin para consolidad un vector formado por el subconjunto de los elementos pares del vector

    Reduccin

    Tail Recursion

    aux([1,2,3], 0, 0) = aux([1,2,3], 1, 1) = aux ([1,2,3], 2, 3) = aux ([1,2,3], 3, 6) = 6

  • @javiervelezreye 35

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    D. Evaluacin Parcial

    II. Tcnicas de Programacin Funcional

    El uso de clausuras permite transformar una funcin para que pueda evaluarse de manera parcial resolviendo slo algunos de sus parmetros. El resultado es una nueva funcin con menos grados de libertad donde los parametros ya evaluados se jan a un valor concreto y el resto quedan como variables libres.

    function color(rr) { return function (gg) { return function (bb) { return [rr, gg, bb] ; }; }; }

    I. Dimensiones Contractuales

    A diferencia de lo que ocurre en otros paradigmas, el diseo funcional de abstracciones 2ene dos dimensiones de denicin, la dimensin espacial y la dimensin temporal.

    En la dimensin temporal cada fase conduce a una etapa de resolucin parcial de parmetros

    La dimensin espacial vincula convencionalmente valores actuales a parmetros

    Desde la fase 1 a la fase 2 se resuelve el parmetro rr y quedan dos dimensiones libres de movimiento (gg, bb) II. Reduccin Dimensional

    Cada fase de aplicacin temporal de parmetros conduce a una reduccin dimensional en el espacio del problema.

    bb

    gg rr

    bb

    gg

    rr = cc

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

  • @javiervelezreye 36

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    D. Evaluacin Parcial

    II. Tcnicas de Programacin Funcional

    El uso de la evaluacin parcial permite que el programador vaya resolviendo de forma faseada la evaluacin de una funcin a medida que va disponiendo de los argumentos actuales necesarios. En estos casos, el diseo de la funcin debe cuidarse para garan2zar que el orden en el que se demandan los parmetros a lo largo del 2empo corresponde con el esperado en el contexto previsto de uso.

    Ejemplo. Evaluacin por Fases

    function schema (scheme) { var uri = { scheme : scheme }; return function (host) { uri.host = host; return function (port) { uri.port = port; return function (path) { uri.path = path; return function () { return uri; }; }; }; }; }

    Se arEcula un proceso de construccin por fases que permite inyectar las partes de una Uri. Este esquema recuerda al patrn Builder de OOP pero usando nicamente funciones

    var host = schema('http'); var port = host('foo.com'); var path = port(80); var uri = path('index.html'); uri();

    Aunque la aplicacin de este esquema induce un estricto orden en la resolucin para-mtrica permite resolver por fases el proceso construcEvo a medida que se dispone de los datos

  • @javiervelezreye 37

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    D. Evaluacin Parcial

    II. Tcnicas de Programacin Funcional

    Otro escenario protolpico del uso de la evaluacin parcial se da en la comunicacin entre funciones proveedoras y clientes. El proveedor resuelve parcialmente una funcin reduciendo as el nmero 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 diseo funcional debe fasearse teniendo en cuenta la intervencin primera del proveedor y posterior del cliente.

    Transferencia Proveedor - Consumidor

    function RuleEngine (ctx) { return function eval(rule) { return function () { var args = [].slice.call(arguments); if (rule.trigger.apply(ctx, args)) return rule.action.apply(ctx, args); }; }; } var rE = RuleEngine({age: 18, login: false});

    rE ({ trigger: function (age) { return age > this.age; }, action: function () { return this.login = true; } })(19); rE ({ trigger: function () { return this.login; }, action: function () { return 'Bienvenido!'; } })();

    El proveedor resuelve parcialmente una funcin eval y la entrega como resultado a la funcin cliente

    La funcin obtenida del proveedor permite al cliente evaluar reglas que se apoyan en las variables retenidas

    rE ctx function eval(rule) {}

    Proveedor

    RuleEngine RuleEngine(ctx)

    Cliente

  • @javiervelezreye 38

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    E. Composicin Funcional

    II. Tcnicas de Programacin Funcional

    Dado que en programacin funcional las abstracciones son meras transformaciones que no pueden ar2cular un algoritmo secuencial, es frecuente modelar el secuenciamiento en base a la composicin. De esta manera, el valor de retorno de una funcin sirve de entrada para la funcin subsiguiente.

    function clean (s){ return s.trim(); } function words (s){ return s.split(' '); } function count (s){ return s.length; } count( words( clean('La FP en JS Mola!!!') ) );

    clean

    words

    count

    s

    5 La cascada de composicin funcional se recorre en senEdo inverso al natural. Los datos comienzan por la funcin ms interna (clean) y atraviesan la cadena de composicin ascendentemente hasta la cima (count). En el captulo siguiente estudiaremos patrones que conducen a una lectura descendente ms natural

    La organizacin composiEva de funciones conduce a arquitecturas centradas en las transformaciones que los datos atraviesan en cascada

  • @javiervelezreye 39

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    E. Composicin Funcional

    II. Tcnicas de Programacin Funcional

    En ocasiones la forma en la que se denen las abstracciones funcionales no es compa2ble con los procesos de composicin. Para poder ar2cular adecuadamente dichos procesos debemos tener en cuenta dos reglas de transformacin funcional que puede ser necesario aplicar para conseguir funciones composi2vas.

    El Epo del parmetro de entrada de una funcin debe ser compaEble con el Epo del valor de retorno devuelto por la funcin anterior para que la composicin pueda arEcularse con xito

    II. CompaQbilidad Rango-Dominio

    I. Dominio Simple Dado que una funcin f devuelve un nico valor de retorno, el nmero de parmetros que acepta una funcin g cuando se compone con f debe ser exactamente uno. Para miEgar este problema es posible encapsular los resultados de f en una estructura de datos y/o resolver todos los parmetros de g menos uno por medio de evaluacin parcial

    F

    G T

    U El Epo de salida T debe ser compaEble con el Epo de entrada U. En trminos OOP diramos que T debe ser subEpo de U

    count( words( clean(s) ) );

    [String]-> Number String -> [String] String -> String

    neg( square( {stack:[3]} ) );

    function square(r) { var e = r.stack.pop(); return { value: e*e, stack: r.stack }; } function neg(r) { r.stack.push(-r.value); return r; }

  • @javiervelezreye 40

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    F. Transformacin Mondica

    II. Tcnicas de Programacin Funcional

    El diseo de funciones debe hacerse garan2zando la ausencia de efectos colaterales de manera que cada funcin slo dependa de sus parmetros de entrada. Sin embargo, en el mundo real es frecuente requerir que una funcin realice operaciones que dependan del entorno (dependencias de estado, operaciones de E/S, etc.). Las tcnicas de transformacin mondica garan2zan la ausencia de efectos colaterales a la vez que conservan la capacidad composi2va.

    Supongamos que tenemos una librera de funciones matemEcas de un solo parmetro que operan con nmeros y devuelven un nmero. Por moEvos de depuracin estas funciones emiten mensajes a la consola

    function inv (x) { console.log('invertir'); return 1/x; } function sqr (x) { console.log('cuadrado'); return x*x; } function inc (x) { console.log('incremento'); return x+1; } function dec (x) { console.log('decremento'); return x-1; }

    Dado que la traza por consola se considera un efecto colateral indeseable se transforman las funciones en puras parametrizando la traza como valor anexo de salida

    function inv (x) { return { value: 1/x, log: ['invertir'] }; } function sqr (x) { return { value: x*x, log: ['cuadrado'] }; } function inc (x) { return { value: x+1, log: ['incrementar'] }; } function dec (x) { return { value: x-1, log: ['decrementar'] }; }

    Ejemplo. Monada Escritor

  • @javiervelezreye 41

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    F. Transformacin Mondica

    II. Tcnicas de Programacin Funcional

    El diseo de funciones debe hacerse garan2zando la ausencia de efectos colaterales de manera que cada funcin slo dependa de sus parmetros de entrada. Sin embargo, en el mundo real es frecuente requerir que una funcin realice operaciones que dependan del entorno (dependencias de estado, operaciones de E/S, etc.). Las tcnicas de transformacin mondica garan2zan la ausencia de efectos colaterales a la vez que conservan la capacidad composi2va.

    Ahora las funciones son puras pero han perdido su capacidad composiEva puesto que incumplen la regla de compaEbilidad Rango-Dominio. Es necesario, en primer lugar, crear una funcin unit que eleve valores unitarios desde el Epo simple (Number) al Epo mondico (valor + log)

    Ahora podemos crear una funcin bind que permita componer nuestras funciones anteriores sin necesidad de alterarlas. Esta funcin recibe un valor mondico (entrada + log acumulado) y una de nuestras funciones. La funcin bind primero desenvuelve la monada, despus aplica la funcin pasada como parmetro y anexa la traza de la misma al log acumulado. Finalmente devuelve la estructura mondica con los resultados obtenidos

    function unit (value) { return { value: value, log : [] }; }

    Ejemplo. Monada Escritor

    function bind (m, fn) { var r = fn(m.value); return { value : r.value, log : m.log.concat(r.log) }; return this; }

  • @javiervelezreye 42

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    F. Transformacin Mondica

    II. Tcnicas de Programacin Funcional

    El diseo de funciones debe hacerse garan2zando la ausencia de efectos colaterales de manera que cada funcin slo dependa de sus parmetros de entrada. Sin embargo, en el mundo real es frecuente requerir que una funcin realice operaciones que dependan del entorno (dependencias de estado, operaciones de E/S, etc.). Las tcnicas de transformacin mondica garan2zan la ausencia de efectos colaterales a la vez que conservan la capacidad composi2va.

    Con las funciones de transformacin mondica unit & bind hemos creado una solucin para garanEzar la composicin funcional eliminando los efectos colaterales de traza por pantalla

    Ejemplo. Monada Escritor

    bind( bind( unit(3), sqr ), neg );

    unit

    sqr

    inc

    3

    { value: 10, log: [ 'cuadrado', 'incremento'] }

    El valor primiEvo 3, se transforma primero al Epo mondico y luego se compone con la funcin sqr e inc por medio de la asistencia que proporciona la funcin bind

  • @javiervelezreye 43

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    F. Transformacin Mondica

    II. Tcnicas de Programacin Funcional

    El diseo de funciones debe hacerse garan2zando la ausencia de efectos colaterales de manera que cada funcin slo dependa de sus parmetros de entrada. Sin embargo, en el mundo real es frecuente requerir que una funcin realice operaciones que dependan del entorno (dependencias de estado, operaciones de E/S, etc.). Las tcnicas de transformacin mondica garan2zan la ausencia de efectos colaterales a la vez que conservan la capacidad composi2va.

    Existen muchos Epos de efectos colaterales que pueden evitarse por medio de la aplicacin de tcnicas de composicin mondica. Dado que cada Epo de efecto colateral requiere una lgica unit y bind especca es buena idea expresar estas tcnicas como objetos donde unit se codique como constructor y bind como mtodo miembro del protoEpo

    Ejemplo. Monada Escritor

    function Writer (value) { this.value = value; this.log = []; } Writer.prototype.bind = function (fn) { var m = fn(this.value); var result = new Writer(m.value); result.log = this.log.concat(m.log); return result; };

    var r = new Writer(3) .bind(sqr) .bind(inc);

    Aunque desde un punto de vista pragmEco esta operaEva resulta cmoda y natural debemos ser conscientes de que se apoya en encapsulacin de estado

  • @javiervelezreye 44

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    G. Inversin de Control

    II. Tcnicas de Programacin Funcional

    Las programacin funcional permite ar2cular dos 2pos de arquitecturas complementarias. Las arquitecturas centradas en los datos jan una coleccin de datos de entrada y hacen atravesar en torno a ellos una coleccin de transformaciones funcionales. Ortogonalmente, las arquitecturas centradas en la transformacin establecen una cadena composi2va de funciones que es atravesada por diversas colecciones de datos. Las tcnicas de inversin de control son una pasarela para conver2r un esquema arquitectnico en el contrario y viceversa.

    data('La FP en JS Mola!!!') .do(clean) .do(words) .do(count);

    function data (value) { return { value: value, do: function (fn) { this.value = fn(this.value); return this; } }; }

    count words clean S 5

    Arquitecturas Centradas en los Datos

    Las arquitecturas centradas en los datos jan un conjunto de datos y permiten realizar transformaciones pasadas como parmetros en orden superior

  • @javiervelezreye 45

    Tcnicas de Programacin Funcional Programacin Funcional en JavaScript

    G. Inversin de Control

    II. Tcnicas de Programacin Funcional

    Las programacin funcional permite ar2cular dos 2pos de arquitecturas complementarias. Las arquitecturas centradas en los datos jan una coleccin de datos de entrada y hacen atravesar en torno a ellos una coleccin de transformaciones funcionales. Ortogonalmente, las arquitecturas centradas en la transformacin establecen una cadena composi2va de funciones que es atravesada por diversas colecciones de datos. Las tcnicas de inversin de control son una pasarela para conver2r un esquema arquitectnico en el contrario y viceversa. Arquitecturas Centradas en la Transformacin

    Las arquitecturas centradas en la transformacin establecen una cadena de composicin de transformaciones funcionales por las que atraviesan disEntas colecciones de datos

    clean words count S 5

    function clean (s) { return s.trim(); } function words (s) { return s.split(' '); } function count (s) { return s.length; } count( words( clean('La FP en JS Mola!!!') ) );

    En el siguiente captulo estudiaremos patrones dedicados a establecer transformaciones para converEr arquitecturas centradas en los datos a arquitecturas centradas en transformacin y viceversa

  • Javier Vlez Reyes @javiervelezreye

    [email protected]

    4 Patrones de Diseo Funcional

    Adaptacin Funcional & Evaluacin Parcial Decoracin & Combinacin Secuenciamiento & Inversin de Control Programacin Ambiental & Frameworks Funcionales Op2mizacin & Asincrona

    Patron

    es de Diseo

    Fun

    cion

    al

    Prog

    ramac

    in Fu

    nciona

    l en Java

    Scrip

    t

  • @javiervelezreye 47

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    Las tcnicas 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 denidos. Esto da pie a iden2car este 2po de prc2cas como soluciones cannicas de validez probada que juegan el papel de patrones de diseo en el marco de la programacin funcional. A lo largo de este captulo describiremos 9 categoras de patrones funcionales.

    I. Introduccin

    Los patrones de decoracin transforman funciones incluyendo lgica de decoracin

    Decoracin Los patrones de secuencia-miento proporcionan control de ujo dirigido por los datos

    Secuenciamiento Los patrones de inversin invierten el contrato funcional para adaptarlo al contexto

    Inversin de Control

    Los patrones de programacin ambiental denen entornos de denicin funcional

    P. Ambiental Los patrones de op2mizacin transforman funciones para adaptarlas en 2empo y memoria

    OpQmizacin Los patrones de asincrona transforman funciones para conver2rlas en no bloqueantes

    Asincrona

    Los patrones de adaptacin adaptan funciones a dis2ntos contextos de uso

    Adaptacin Los patrones de evaluacin parcial transforman funciones para poder evaluarlas por fases

    Evaluacin Parcial

  • @javiervelezreye 48

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La adaptacin funcional es una de las capacidades de la programacin funcional que persigue transformar el proto2po de una funcin para adaptarla a las peculiaridades especcas del contexto de explotacin. La aplicacin de adaptaciones convierte a las arquitecturas funcionales en sistemas con alta plas2cidad que permite alcanzar cotas elevadas de reu2lizacin. En esta seccin presentamos algunos patrones en este sen2do.

    II. Patrones de Adaptacin Funcional

    Patrn reverse

    function reverse (fn) { return function () { var args = [].slice.call(arguments); var iargs = [].concat(args).reverse(); return fn.apply(this, iargs); }; }

    var add = function (x, y) { return x + y; }; var sub = function (x, y) { return x - y; }; var radd = reverse (add); var rsub = reverse (sub); radd (2, 8) === add (2, 8); // true radd (2, 8) === add (8, 2); // true rsub (2, 8) === sub (2, 8); // false rsub (2, 8) === sub (8, 2); // true

    El patrn reverse adapta una funcin pasada como parmetro para inverEr el orden de sus parmetros de entrada

    La inversin de parmetros no afecta a las operaciones conmutaEvas (add) pero s a las que no cumplen esta propiedad (sub)

    sub (8,4) 4

    rsub (8,4) -4

    rsub = reverse(sub)

  • @javiervelezreye 49

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La adaptacin funcional es una de las capacidades de la programacin funcional que persigue transformar el proto2po de una funcin para adaptarla a las peculiaridades especcas del contexto de explotacin. La aplicacin de adaptaciones convierte a las arquitecturas funcionales en sistemas con alta plas2cidad que permite alcanzar cotas elevadas de reu2lizacin. En esta seccin presentamos algunos patrones en este sen2do.

    II. Patrones de Adaptacin Funcional

    Patrn swap

    function swap (fn, p) { return function () { var args = [].slice.call (arguments); var temp = args[p[0]]; args[p[0]] = args[p[1]]; args[p[1]] = temp; return fn.apply(this, args); }; }

    var exp = function (x, y, z){ return x + y * z; }; var expSwp1 = swap (exp, [0, 1]); var expSwp2 = swap (exp, [0, 2]); exp(2,3,5); // 17 expSwp1(2,3,5); // 13 expSwp2(2,3,5); // 11

    El patrn swap adapta una funcin pasada como parmetro para inverEr el orden de un par de parmetros de entrada

    La inversin de parmetros permite reinterpretar expresiones de manera transparente para el usuario externo. Veremos su uElidad ms adelante

    exp (2,3,5) 17

    expSwp (2,3,5) 11

    expSwp = swap(exp, [0,2])

  • @javiervelezreye 50

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La adaptacin funcional es una de las capacidades de la programacin funcional que persigue transformar el proto2po de una funcin para adaptarla a las peculiaridades especcas del contexto de explotacin. La aplicacin de adaptaciones convierte a las arquitecturas funcionales en sistemas con alta plas2cidad que permite alcanzar cotas elevadas de reu2lizacin. En esta seccin presentamos algunos patrones en este sen2do.

    II. Patrones de Adaptacin Funcional

    Patrn arity

    function arity (n) { return function (fn) { return function () { var args = [].slice.call(arguments, 0, n-1); return fn.apply(this, args); }; }; }

    var unary = arity (1); ['1', '2', '3'].map(parseInt)); // Error ['1', '2', '3'].map(unary(parseInt))); // Ok

    El patrn arity adapta una funcin de manera que acepte exactamente un nmero especico de parmetros ignorando el resto

    La limitacin del nmero de parmetros que puede aceptar una funcin puede resultar muy El a veces. En el ejemplo, la funcin parseInt acepta un String y opcionalmente la base (radix). Sin embargo queremos que parseInt consuma exactamente un parmetro cada vez que es invocado para recorrer adecuadamente el array

    unary f(2,3,5) f(2)

  • @javiervelezreye 51

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La adaptacin funcional es una de las capacidades de la programacin funcional que persigue transformar el proto2po de una funcin para adaptarla a las peculiaridades especcas del contexto de explotacin. La aplicacin de adaptaciones convierte a las arquitecturas funcionales en sistemas con alta plas2cidad que permite alcanzar cotas elevadas de reu2lizacin. En esta seccin presentamos algunos patrones en este sen2do.

    II. Patrones de Adaptacin Funcional

    Patrn variadic

    function variadic (fn) { return function () { var args = [].slice.call(arguments); var other = args.splice(0, fn.length-1); return fn.apply(this, other.concat([args])); }; }

    var basket = variadic ( function (date, user, products){ console.log('[%s] - %s:', date, user); console.log(products); }); basket( 'hoy', 'jvelez', 'platanos', 'manzanas', 'peras');

    Pretendemos imitar la capacidad de elipsis (args) que disponen otros lenguajes como lEmo parmetro. Diseamos una funcin incluyendo un lEmo parmetro args:

    foo(2, 3, 5, 8)

    function foo(x, y, args) {}

    x = 2 y = 3 args = 5

    vfoo(2, 3, 5, 8) x = 2 y = 3 args = [5, 8]

    vfoo = variadic(foo)

  • @javiervelezreye 52

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La evaluacin parcial ofrecen estrategias de transformacin funcional que permiten conver2r una funcin completa en otra que se evala por fases. Como ya discu2mos en el captulo 3, esta tcnica resulta muy 2l para reducir la dimensin de una transformacin de forma progresiva y ar2cular procesos de comunicacin entre funciones proveedoras y funciones cliente. En esta seccin describimos patrones de evaluacin parcial.

    III. Patrones de Evaluacin Parcial

    Patrn rst

    function first () { var fn = arguments [0]; var params = [].slice.call(arguments, 1); return function () { var args = [].slice.call(arguments); return fn.apply(this, params.concat(args)); }; }

    var ip = function (a, b, c, d) { return [a, b, c, d]; }; 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]

    El patrn rst adapta una funcin resolviendo los n primeros parmetros de la misma

    ip (192,168,1,1) [192,168,1,1]

    prvIp = first(ip, 192, 168)

    prvIp

    [192,168] [192,168,1,1] (1,1)

  • @javiervelezreye 53

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La evaluacin parcial ofrecen estrategias de transformacin funcional que permiten conver2r una funcin completa en otra que se evala por fases. Como ya discu2mos en el captulo 3, esta tcnica resulta muy 2l para reducir la dimensin de una transformacin de forma progresiva y ar2cular procesos de comunicacin entre funciones proveedoras y funciones cliente. En esta seccin describimos patrones de evaluacin parcial.

    III. Patrones de Evaluacin Parcial

    Patrn last

    function last () { var fn = arguments[0]; var params = [].slice.call(arguments, 1); return function () { var args = [].slice.call(arguments); return fn.apply(this, args.concat(params)); }; }

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

    De manera complementaria, el patrn last adapta una funcin resolviendo los n lEmos parmetros de la misma

    ip (192,168,1,1) [192,168,1,1]

    gwIp = last(ip, 1, 1)

    gwIp

    [1, 1] [192,168,1,1] (192,168)

  • @javiervelezreye 54

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La evaluacin parcial ofrecen estrategias de transformacin funcional que permiten conver2r una funcin completa en otra que se evala por fases. Como ya discu2mos en el captulo 3, esta tcnica resulta muy 2l para reducir la dimensin de una transformacin de forma progresiva y ar2cular procesos de comunicacin entre funciones proveedoras y funciones cliente. En esta seccin describimos patrones de evaluacin parcial.

    III. Patrones de Evaluacin Parcial

    Patrn parQal & rparQal

    function partial (fn) { return function (x) { return function (y) { return fn.call(this, x, y); }; }; } function rpartial (fn) { return function (x) { return function (y) { return fn.call(this, y, x); }; }; }

    var add = partial(function (x, y) { return x + y }); var sub = rpartial(function (x, y) { return x - y }); var inc = add(1); var dec = sub(1); [inc(3), dec(4)];

    El patrn parEal proyecta en la dimensin temporal una funcin binaria en dos fases de evaluacin

    add

    add = partial(add)

    add

    (2,3) 5

    2

    add(2) 3 5 El patrn parEal puede evaluarse a izquierdas o a derechas

  • @javiervelezreye 55

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La evaluacin parcial ofrecen estrategias de transformacin funcional que permiten conver2r una funcin completa en otra que se evala por fases. Como ya discu2mos en el captulo 3, esta tcnica resulta muy 2l para reducir la dimensin de una transformacin de forma progresiva y ar2cular procesos de comunicacin entre funciones proveedoras y funciones cliente. En esta seccin describimos patrones de evaluacin parcial.

    III. Patrones de Evaluacin Parcial

    Patrn curry

    function curry (fn) { return (function aux (args) { if (args.length >= fn.length) { return fn.apply(this, args); } else return function () { var nargs = [].slice.call(arguments); return aux(args.concat(nargs)); }; })([]); }

    var Ip = function (a, b, c, d) { return [a, b, c, d]; }; var cIp = curry(Ip); [ cIp(192, 168, 1, 1), cIp(192, 168, 1)(1), cIp(192, 168)(1, 1), cIp(192, 168)(1)(1), cIp(192)(168, 1, 1), cIp(192)(168, 1)(1)]

    La aplicacin de los parmetros a la funcin curricada puede aplicarse de forma exible cuando se dispongan sus valores. Eso si, los parmetros siempre deben aplicarse en orden

    El patrn curry exEende el patrn parEal para aplicarlo a funciones con cualquier nmero de parmetros

    f

    f

    (a,b,c) r

    r

    a b

    c

  • @javiervelezreye 56

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La evaluacin parcial ofrecen estrategias de transformacin funcional que permiten conver2r una funcin completa en otra que se evala por fases. Como ya discu2mos en el captulo 3, esta tcnica resulta muy 2l para reducir la dimensin de una transformacin de forma progresiva y ar2cular procesos de comunicacin entre funciones proveedoras y funciones cliente. En esta seccin describimos patrones de evaluacin parcial.

    III. Patrones de Evaluacin Parcial

    Patrn rcurry

    function curry (fn) { return (function aux (args) { if (args.length >= fn.length) { return fn.apply(this, args); } else return function () { var nargs = [].slice.call(arguments); return aux(nargs.concat(args)); }; })([]); }

    var Ip = function (a, b, c, d) { return [a, b, c, d]; }; var rcIp = rcurry(Ip); [ rcIp(192, 168, 1, 1), rcIp(168, 1, 1)(192), rcIp(1, 1)(192, 168), rcIp(1, 1)(168)(192), rcIp(1)(192, 168, 1), rcIp(1)(168, 1)(192)]

    El patrn rcurry funciona de manera inversa a curry pero Eene una forma de uso parEcular cada fase re l lena parmetros por el nal pero el orden de aplicacin de ellos en cada fase es de izquierda a derecha

    El patrn rcurry exEende el patrn parEal para aplicarlo a funciones con cualquier nmero de parmetros

    f

    f

    (a,b,c) r

    r

    c b

    a

  • @javiervelezreye 57

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La evaluacin parcial ofrecen estrategias de transformacin funcional que permiten conver2r una funcin completa en otra que se evala por fases. Como ya discu2mos en el captulo 3, esta tcnica resulta muy 2l para reducir la dimensin de una transformacin de forma progresiva y ar2cular procesos de comunicacin entre funciones proveedoras y funciones cliente. En esta seccin describimos patrones de evaluacin parcial.

    III. Patrones de Evaluacin Parcial

    Patrn uncurry

    El patrn uncurry deshace una cu r r icac in pa ra obtener una funcin con una nica fase de evaluacin

    function uncurry (fn) { return function () { var args = [].slice.call(arguments); return args.reduce(function (ac, arg){ return (ac = ac(arg)); }, fn); }; }

    var cadd = function (x) { return function (y) { return function (z) { return x + y + z; }; }; }; var add = uncurry (cadd); cadd(1)(2)(3); // 6 add(1,2,3); // 6

    Si tomamos una funcin en aplicacin parcial y le aplicamos el algoritmo de descurricacin obtenemos una funcin evaluable en una sola fase

    f

    r

    a b

    c f (a,b,c) r

  • @javiervelezreye 58

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    Las capacidades adapta2vas de la programacin funcional permiten denir nuevas funcionas resultantes de un proceso de decoracin de funciones pasadas en orden superior o de una combinacin estratgica de dos funciones. Esto ofrece posibilidades de intercesin y transformacin funcional que exibilizan el uso de abstracciones funcionales en diferentes contextos de uso. En esta seccin presentamos algunos patrones de este 2po.

    IV. Patrones de Decoracin & Combinacin

    Patrn Qmes

    function times (n) { return function (fn) { var times = 0; return function () { if (times < n) { times++; return fn.apply(this, arguments); } }; }; }

    var log = function (msg) { console.log(msg) }; var olog = times(1)(log); olog('JS Mola!'); >> JS Mola! olog('JS Mola!');

    El decorador Emes controla la ejecucin de una funcin limitando el nmero mximo de invocaciones

    olog

    times, n=1

    log >> 'msj' >> 'msj' >> 'msj'

    msj msj msj

    >> 'msj' msj msj msj

    olog = times(1)(log)

  • @javiervelezreye 59

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    Las capacidades adapta2vas de la programacin funcional permiten denir nuevas funcionas resultantes de un proceso de decoracin de funciones pasadas en orden superior o de una combinacin estratgica de dos funciones. Esto ofrece posibilidades de intercesin y transformacin funcional que exibilizan el uso de abstracciones funcionales en diferentes contextos de uso. En esta seccin presentamos algunos patrones de este 2po.

    IV. Patrones de Decoracin & Combinacin

    Patrn maybe

    function maybe (fn) { return function () { var args = [].slice.call(arguments); var callable = arguments.length >= fn.length && args.every(function (p) { return (p !== null); }); if (callable) return fn.apply(this, args); }; }

    var add = function (x, y) { return x + y; }; var mbadd = maybe (add, 2); console.log(mbadd(3)); // undefined console.log(mbadd(2, 3)); // 5

    El patrn maybe comprueba si el nmero de parmetros formales coincide con el de argumentos proporcionados y si ninguno de ellos es null. Slo en ese caso invoca la funcin

    mbadd

    add 5 (2,3)

    undefined 5

    (3) (2,3)

    mbadd = maybe(add)

  • @javiervelezreye 60

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    Las capacidades adapta2vas de la programacin funcional permiten denir nuevas funcionas resultantes de un proceso de decoracin de funciones pasadas en orden superior o de una combinacin estratgica de dos funciones. Esto ofrece posibilidades de intercesin y transformacin funcional que exibilizan el uso de abstracciones funcionales en diferentes contextos de uso. En esta seccin presentamos algunos patrones de este 2po.

    IV. Patrones de Decoracin & Combinacin

    Patrn before & ajer

    function before (dn) { return function (fn) { return function () { dn.apply(this, arguments); return fn.apply(this, arguments); }; }; } function after (dn) { return function (fn) { return function () { var r = fn.apply(this, arguments); dn.apply(this, arguments); return r; }; }; }

    var add = function (x, y) { return x + y; }; var b = function () { console.log ('Before'); }; var a = function () { console.log ('After'); }; var beforeAdd = before(b)(add); var afterAdd = before(a)(add); beforeAdd (2,3); // >> 'Before' 5 afterAdd (2,3); // 5 >> 'After'

    Los patrones before y aner ejecutan una funcin decorado antes y despus de ejecutar la funcin que se pasa como parmetro en una segunda fase de evaluacin

    add 5 (2,3)

    ajerAdd 5 >> 'After'

    (2,3)

    afterAdd = after(a)(add);

  • @javiervelezreye 61

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    Las capacidades adapta2vas de la programacin funcional permiten denir nuevas funcionas resultantes de un proceso de decoracin de funciones pasadas en orden superior o de una combinacin estratgica de dos funciones. Esto ofrece posibilidades de intercesin y transformacin funcional que exibilizan el uso de abstracciones funcionales en diferentes contextos de uso. En esta seccin presentamos algunos patrones de este 2po.

    IV. Patrones de Decoracin & Combinacin

    Patrn around

    function around (dn) { return function (fn) { return function () { var args = [].slice.call(arguments); args = [dn.bind(this)].concat(args); return fn.apply(this, args); }; }; }

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

    El patrn around permite disear funciones que reciben como primer parmetro una funcin que representa un punto de intercesin donde se inyecta cdigo desde el exterior

    add 5 (2,3)

    gAdd g(); g(); 5 (2,3)

    gAdd = around(g)(add);

    Dentro de la denicin de la funcin add, around () supone una invocacin a la funcin g, que es inyectada por el cliente

  • @javiervelezreye 62

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    Las capacidades adapta2vas de la programacin funcional permiten denir nuevas funcionas resultantes de un proceso de decoracin de funciones pasadas en orden superior o de una combinacin estratgica de dos funciones. Esto ofrece posibilidades de intercesin y transformacin funcional que exibilizan el uso de abstracciones funcionales en diferentes contextos de uso. En esta seccin presentamos algunos patrones de este 2po.

    IV. Patrones de Decoracin & Combinacin

    Patrn provided & except

    function provided (pn) { return function (fn) { return function () { if (pn.apply(this, arguments)) return fn.apply(this, arguments); }; }; } function except (pn) { return function (fn) { return function () { if (!pn.apply(this, arguments)) return fn.apply(this, arguments); }; }; }

    var add = function (x, y) { return x+y; }; var positive = function (x, y) { return x*y>0; }; 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]

    Los patrones provided y except ejecutan condicionalmente una funcin cuando se saEsface o no, respecEvamente un predicado lgico pasado como argumento

    add 5 (2,3)

    padd 5 undefined

    (2,3) (-2,3)

    padd = provided(positive)(add);

  • @javiervelezreye 63

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La programacin funcional est basada en la construccin de abstracciones descritas como expresiones funcionales. El concepto de secuenciamiento algortmico y de control de ujo, tal y como se en2ende en la programacin impera2va, no es de aplicacin en este paradigma. Los patrones de secuenciamiento desvelan formas con las que es posible emular hasta cierto punto un es2lo de programacin secuencial con direc2vas de control de ujo.

    V. Patrones de Composicin & Secuenciamiento

    Patrn forEach

    function forEach (data, fn, self) { (function aux (data, index, fn) { fn.call(self, data[index], index, data); if (index < data.length - 1) aux(data, index + 1, fn); })(data, 0, fn); }

    forEach ([1,2,3], function (item, idx) { console.log(idx, item); });

    La funcin manejadora sigue un contrato basado en tres parmetros. El primero corresponde con el elemento en curso, el segundo con el ndice que ocupa dentro de la coleccin y el tercero con la propia coleccin

    El patrn forEach encapsula una inmersin por recorrido de la coleccin pasada como primer parmetro

    1

    2

    3

    f

    f

    f

    La funcin fn se aplica secuencial-mente a todos los elementos de la coleccin desde el primero al lEmo

  • @javiervelezreye 64

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La programacin funcional est basada en la construccin de abstracciones descritas como expresiones funcionales. El concepto de secuenciamiento algortmico y de control de ujo, tal y como se en2ende en la programacin impera2va, no es de aplicacin en este paradigma. Los patrones de secuenciamiento desvelan formas con las que es posible emular hasta cierto punto un es2lo de programacin secuencial con direc2vas de control de ujo.

    V. Patrones de Composicin & Secuenciamiento

    Patrn reduce La funcin f combina secuencial-mente cada elemento de la coleccin tomando el 0 como valor inicial

    function reduce (data, fn, base, self) { var ac = base; forEach(data, function(e, i, data) { ac = fn.call(self, ac, data[i], i, data); }, self); return ac; }

    reduce ([1,2,3], function (a, e) { return e + a; }, 0);

    El patrn reduce encapsula una inmersin por acumulacin de la coleccin pasada como primer parmetro. La implementacin interna se apoya en forEach

    1 0

    2

    f

    f

    La funcin manejadora sigue un contrato basado en cuatro parmetros. El primero corresponde con el acumulador, el segundo con el elemento en curso, el tercero con el ndice que ocupa dentro de la coleccin y el lEmo con la propia coleccin

    3

    f

  • @javiervelezreye 65

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La programacin funcional est basada en la construccin de abstracciones descritas como expresiones funcionales. El concepto de secuenciamiento algortmico y de control de ujo, tal y como se en2ende en la programacin impera2va, no es de aplicacin en este paradigma. Los patrones de secuenciamiento desvelan formas con las que es posible emular hasta cierto punto un es2lo de programacin secuencial con direc2vas de control de ujo.

    V. Patrones de Composicin & Secuenciamiento

    Patrn rReduce La funcin f combina secuencial-mente en orden inverso cada elemento de la coleccin tomando el 0 como valor inicial

    function rReduce (data, fn, base, self) { var iData= [].concat(data).reverse(); return reduce(iData, fn, base, self); }

    rReduce ([1,2,3], function (a, e) { return e + a; }, 0); El carcter asociaEvo de la operacin de

    suma provoca que el resultado sea equivalente al anterior. Su implementa-cin interna aplica un reduce sobre la inversin del orden de la coleccin

    3 0

    2

    1

    f

    f

    f

    La funcin manejadora sigue un contrato basado en cuatro parmetros. El primero corresponde con el acumulador, el segundo con el elemento en curso, el tercero con el ndice que ocupa dentro de la coleccin y el lEmo con la propia coleccin

  • @javiervelezreye 66

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La programacin funcional est basada en la construccin de abstracciones descritas como expresiones funcionales. El concepto de secuenciamiento algortmico y de control de ujo, tal y como se en2ende en la programacin impera2va, no es de aplicacin en este paradigma. Los patrones de secuenciamiento desvelan formas con las que es posible emular hasta cierto punto un es2lo de programacin secuencial con direc2vas de control de ujo.

    V. Patrones de Composicin & Secuenciamiento

    Patrn map La funcin f se aplica secuencial-mente a cada elemento de la coleccin y genera como resultado una nueva coleccin transformada

    function map (data, fn, self) { return reduce(data, function (ac, item) { return ac.concat(fn.call(self, item)); }, [], self); }

    map([1,2,3], function (e) { return e * e; });

    El patrn map se implementa interna-mente aplicando una reduccin. La estrategia de acumulacin consiste en parEr de un array vacio e ir aadiendo a cada paso cada item transformado de la coleccin al acumulador

    1

    2

    3

    f

    f

    f

    La funcin manejadora sigue un contrato basado en tres parmetros. El primero corresponde con el elemento en curso, el segundo con el ndice que ocupa dentro de la coleccin y el tercero con la propia coleccin

    1

    4

    9

  • @javiervelezreye 67

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La programacin funcional est basada en la construccin de abstracciones descritas como expresiones funcionales. El concepto de secuenciamiento algortmico y de control de ujo, tal y como se en2ende en la programacin impera2va, no es de aplicacin en este paradigma. Los patrones de secuenciamiento desvelan formas con las que es posible emular hasta cierto punto un es2lo de programacin secuencial con direc2vas de control de ujo.

    V. Patrones de Composicin & Secuenciamiento

    Patrn lter El predicado p se aplica secuencial-mente a cada elemento de la coleccin y, si se evala a cierto, lo incluye en la coleccin de salida

    function filter (data, fn, self) { return reduce(data, function (ac, e, i, data) { if (fn.call(self, e, i, data)) ac.push(e); return ac; }, [], self); }

    filter([1,2,3], function (e){ return e % 2 !== 0; });

    El patrn lter se implementa interna-mente aplicando una reduccin. La estrategia de acumulacin consiste en parEr de un array vacio e ir aadiendo a cada paso cada item si se supera el predicado lgico

    1

    2

    3

    p

    p

    p

    La funcin manejadora es un predicado lgico que sigue un contrato basado en tres parmetros. El primero corresponde con el elemento en curso, el segundo con el ndice que ocupa dentro de la coleccin y el tercero con la propia coleccin

    1

    2

    3

  • @javiervelezreye 68

    Patrones de Diseo Funcional Programacin Funcional en JavaScript

    La programacin funcional est basada en la construccin de abstracciones descritas como expresiones funcionales. El concepto de secuenciamiento algortmico y de control de ujo, tal y como se en2ende en la programacin impera2va, no es de aplicacin en este paradigma. Los patrones de secuenciamiento desvelan formas con las que es posible emular hasta cierto punto un es2lo de programacin secuencial con direc2vas de control de ujo.

    V. Patrones de Composicin & Secuenciamiento

    Patrn every & some El predicado p se aplica secuencial-mente a cada elemento de la coleccin y combina cada resultado a travs de la conjuncin lgica

    function every (data, fn, self) { return reduce (data, function (ac, e, i, data) { return ac && fn.call(self, e, i, data); }, true, self); } function some(data, fn, self) { return reduce (data, function (ac, e, i, data) { return ac || fn.call(self, e,