$30 off During Our Annual Pro Sale. View Details »

Programação Funcional em JavaScript na prática com Ramda

Programação Funcional em JavaScript na prática com Ramda

Não existe solução única para todos os problemas em tecnologia. O mesmo acontece para linguagens de programação! Aprenderemos mais sobre elas através do paradigma de programação funcional. Abordaremos paradigmas de programação, programação funcional e conceitos relacionados como funções de primeira classe, alta ordem e puras, estados, imutabilidade, transparência referencial, funções parciais, currying, composição e recursão. Veremos exemplos utilizando JavaScript puro e a biblioteca Ramda.js construída para o estilo de programação funcional.

Marcel dos Santos

July 21, 2018
Tweet

More Decks by Marcel dos Santos

Other Decks in Programming

Transcript

  1. Marcel Gonçalves dos Santos
    @marcelgsantos
    programação funcional
    na prática c
    o
    Ramda
    JavaScript
    em

    View Slide

  2. pensandonaweb.com.br
    desenvolvedor web full-stack
    Marcel Gonçalves dos Santos
    @marcelgsantos

    View Slide

  3. @phpsp
    phpsp.org.br

    View Slide

  4. Interaja nas mídias sociais!


    - fale sobre o evento, palestrantes e conteúdo


    - tire fotos do evento e publique

    - interaja com outros participantes do evento


    - tire dúvidas ou dê feedbacks para os palestrantes

    View Slide

  5. O que é


    programação funcional?

    View Slide

  6. é um paradigma de programação que utiliza
    funções puras e foca na transformação do
    estado

    View Slide

  7. O que é paradigma


    de programação?

    View Slide

  8. são modelos ou estilos de programação
    suportados por linguagens que agrupam
    certas características comuns

    View Slide

  9. os p
    ar
    adigmas de pro
    gr
    amação definem
    c
    om
    o os códigos são es
    tr
    ut
    ur
    ados…

    View Slide

  10. principais paradigmas de programação

    os dois principais paradigmas são o
    imperativo e o declarativo

    View Slide

  11. paradigma imperativo

    descreve a resolução de um problema através de
    comandos que o computador pode compreender
    e executar

    View Slide

  12. paradigma imperativo

    os paradigmas procedural e orientado a
    objetos são exemplos de paradigmas
    imperativos

    View Slide

  13. let result = 0;


    / /
    Imperative code to sum 1 to 10


    for (let i = 0; i
    < =
    10; i
    + +
    ) {


    result += i;


    }


    console.log(result);
    / /
    55

    View Slide

  14. paradigma declarativo

    permite especi
    fi
    car o que deve ser
    computado e não como deve ser computado

    View Slide

  15. paradigma declarativo

    os paradigmas funcional e lógico são
    exemplos de paradigmas declarativos

    View Slide

  16. const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];


    / /
    Declarative code to sum 1 to 10


    const sum = (a, b)
    = >
    a + b;


    const result = numbers.reduce(sum);


    console.log(result);

    View Slide

  17. paradigmas de algumas linguagens de
    programação


    imperativo

    procedural - C e Pascal


    orientado a objetos - C++, Java, PHP, Python e Ruby


    declarativo

    lógico - Prolog


    funcional - Clojure, Elixir, Elm, Erlang, F#, Haskell, Lisp, OCaml e Scala

    View Slide

  18. Programação


    Funcional
    λ

    View Slide

  19. paradigma de programação que utiliza
    funções puras e foca na transformação do
    estado

    View Slide

  20. baseado no cálculo lambda proposto por
    Alonzo Church na década de 30

    View Slide

  21. na programação funcional as funções são
    tratadas como conceito principal

    View Slide

  22. Uma função matemática
    tr
    ata-se de um simples
    mapeamento en
    tr
    e o d
    om
    ínio e o c
    on
    tr
    a-d
    om
    ínio.
    1
    2
    3
    D
    B
    A
    C
    X Y

    View Slide

  23. JavaScript
    λ

    View Slide

  24. presente em todos os lugares como
    navegadores, servidores, mobile, desktop e
    dispositivos IoT

    View Slide

  25. muito popular e utilizada

    View Slide

  26. todos os programadores deveriam aprender

    View Slide

  27. possui suporte para diversas
    funcionalidades de programação funcional

    View Slide

  28. Estado
    λ

    View Slide

  29. o estado de um programa é representado
    pelos valores dos dados armazenados na
    memória em qualquer ponto de execução


    do programa

    View Slide

  30. o estado de uma aplicação é alterado a cada
    interação feita pelo usuário…

    View Slide

  31. …ou pelo próprio sistema e pode ser
    representado por uma estrutura de dados

    View Slide

  32. a maioria dos bugs são relacionados ao
    controle de estado

    View Slide

  33. Funções Puras
    λ

    View Slide

  34. 1. ter parâmetros de entrada

    2. não depender do estado externo

    3. retorno baseado nos valores de entrada

    4. não devem causar efeitos colaterais
    funções puras

    View Slide

  35. / /
    pure or impure function?


    let counter = 0;


    function increment() {


    counter
    + +
    ;


    return counter;


    }


    console.log(increment());
    / /
    1

    View Slide

  36. / /
    pure function (ES5 syntax)


    function add(x, y) {


    return x + y;


    }


    console.log(add(2, 3));
    / /
    5

    View Slide

  37. / /
    pure function (ES6 syntax)


    const add = (x, y)
    = >
    x + y;


    console.log(add(2, 3));
    / /
    5

    View Slide

  38. por que utilizar funções puras?

    são reutilizáveis, componíveis, fáceis de
    testar, fáceis de cachear e paralelizáveis

    View Slide

  39. transparência referencial

    propriedade que garante que a saída de uma
    função pura sempre será a mesma dado um
    mesmo conjunto de argumentos

    View Slide

  40. / /
    referential transparency


    const add = (x, y)
    = >
    x + y;


    console.log(add(2, 3)
    = = =
    5);
    / /
    true


    console.log(5
    = = =
    5);
    / /
    true

    View Slide

  41. pode não ser fácil criar funções puras

    View Slide

  42. porém, a restritividade ajuda a


    melhorar o foco

    View Slide

  43. Mais sobre


    Funções
    λ

    View Slide

  44. funções de alta ordem e

    funções de primeira classe

    são funções que podem ser atribuídas a
    variáveis, passadas como argumentos e
    retornadas de uma função

    View Slide

  45. / /
    high
    -
    order function


    const add = (x, y)
    = >
    x + y;


    const numbers = [1, 2, 3, 4, 5];


    const sum = numbers.reduce(add);


    const sum10 = numbers.reduce(add, 10);


    console.log(sum);
    / /
    15


    console.log(sum10);
    / /
    25

    View Slide

  46. funções anônimas

    funções que não possuem nome e que,
    geralmente, são passadas como argumento
    ou atribuídas

    View Slide

  47. / /
    anonymous function


    const numbers = [1, 2, 3, 4, 5];


    const sum = numbers.reduce((x, y)
    = >
    x + y);


    console.log(sum);
    / /
    15

    View Slide

  48. closures

    funções que possuem acesso à valores do
    escopo externo

    View Slide

  49. /
    /
    closure function


    function greet(greeting) {


    return function (name) {


    return `${greeting} ${name}!`;


    };


    }


    const greet2 = greeting
    =
    >
    name
    =
    >
    `${greeting} ${name}!`;


    console.log(greet('Hello')('Mary'));
    /
    /
    Hello Mary!


    console.log(greet2('Hello')('John'));
    /
    /
    Hello John!

    View Slide

  50. recursão

    é quando uma função é definida em termos de
    si própria, ou seja, quando a função chama ela
    mesma

    View Slide

  51. diferença entre função e procedimento
    (procedure)

    uma função recebe um valor e retorna um
    resultado; um procedimento é um conjunto
    de comandos executados numa ordem

    View Slide

  52. “D
    on
    't think of functi
    on
    s as a
    c
    ol
    lecti
    on
    of ins
    tr
    ucti
    on
    s. Think of
    them as n
    on
    -des
    tr
    uctive
    op
    er
    ati
    on
    s
    on
    input `d
    ou
    ble = n => n * 2;`”
    Eric Ellio
    tt
    , 2016.
    https:/
    /twitter.com/_ericelliott/status/685172918784004097

    View Slide

  53. memoize

    técnica que permite que funções custosas
    sejam cacheadas para execuções posteriores
    mais rápidas

    View Slide

  54. Imutabilidade
    λ

    View Slide

  55. a imutabilidade diz que um dado não pode
    ser alterado após a sua criação

    View Slide

  56. a imutabilidade permite maior con
    fi
    ança e
    evita que erros ocorram

    View Slide

  57. o JavaScript não possui suporte a dados
    imutáveis de forma nativa

    View Slide

  58. porém, pode-se trabalhar com dados
    imutáveis em JavaScript utilizando algumas
    técnicas

    View Slide

  59. Currying e


    aplicação parcial
    λ

    View Slide

  60. o currying é a técnica que permite
    transformar uma função que recebe
    múltiplos argumentos em uma função que…

    View Slide

  61. …recebe apenas um argumento e que
    retorna uma função que aceita os
    argumentos restantes

    View Slide

  62. a aplicação parcial é quando se executa
    uma função e passa apenas parte de seus
    argumentos

    View Slide

  63. a aplicação parcial permite fazer


    a especialização de uma função mais
    genérica

    View Slide

  64. / /
    specialization from a curried function


    / /
    using partial application


    const greet =


    R.curry((greeting, name)
    = >
    `${greeting} ${name}`);


    const greetMorning = greet('Good Morning');


    console.log(greetMorning('Alice'));
    / /
    Good Morning Alice

    View Slide

  65. currying e aplicação parcial são recursos
    muito utilizados em programação funcional

    View Slide

  66. na programação funcional deve-se levar em
    consideração a ordem dos parâmetros

    View Slide

  67. os parâmetros mais genéricos devem vir
    mais para o início e os parâmetros mais
    especí
    fi
    cos devem vir mais para o
    fi
    nal

    View Slide

  68. o JavaScript não possui suporte nativo para
    currying como nas linguagens puramente
    funcionais Elm ou Haskell

    View Slide

  69. Composição


    de Funções
    λ

    View Slide

  70. a composição é o processo de combinar uma
    ou mais funções para criar uma nova função

    View Slide

  71. / /
    composing some functions to achieve a new behaviour


    const sentence = 'estava à toa na vida o meu amor me


    chamou pra ver a banda passar cantando coisas de amor';


    const wordCount = R.length(R.split(' ', sentence));


    console.log(wordCount);
    / /
    19

    View Slide

  72. é uma solução elegante e legível e ajuda a
    evitar a utilização do aninhamento de
    funções

    View Slide

  73. o Ramda possui uma função que permite
    criar uma nova função a partir da
    composição de funções

    View Slide

  74. / /
    create a function using composition


    const sentence = 'estava à toa na vida o meu amor me


    chamou pra ver a banda passar cantando coisas de amor';


    const countWords = R.compose(R.length, R.split);


    console.log(countWords(' ', sentence));
    / /
    19

    View Slide

  75. Biblioteca

    Ramda
    λ

    View Slide

  76. uma biblioteca construída para o estilo de
    programação funcional que facilita a
    utilização de pipelines e dados imutáveis

    View Slide

  77. possui foco no estilo puramente funcional

    View Slide

  78. todas as funções do Ramda são auto-curried

    View Slide

  79. os argumentos das funções do Ramda são
    organizados de forma a facilitar a utilização
    de currying

    View Slide

  80. Caso de Uso 1


    somar os preços dos produtos


    de um carrinho de compras

    View Slide

  81. / /
    shopping cart


    const cart = [


    {id: 1, product: 'iPhone', price: 499},


    {id: 2, product: 'Kindle', price: 179},


    {id: 3, product: 'Macbook Pro', price: 1199},


    ];


    / /
    get prices from shopping cart and sum them

    / /
    using intermediate values


    const cartPrices = R.map(item
    = >
    item.price, cart);


    const cartSum = R.sum(cartPrices);


    console.log(cartSum);
    / /
    1877


    realiza o mapeamento da
    lista de produtos (objetos)
    para uma lista de preços
    (números)
    faz a somatória da lista de
    números e retorna o total
    Passo 1

    View Slide

  82. / /
    shopping cart


    const cart = [


    {id: 1, product: 'iPhone', price: 499},


    {id: 2, product: 'Kindle', price: 179},


    {id: 3, product: 'Macbook Pro', price: 1199},


    ];


    / /
    get prices from shopping cart and sum them

    / /
    using function composition


    const totalCart = R.compose(


    R.sum,


    R.map(item
    = >
    item.price),


    );


    console.log(totalCart(cart));
    / /
    1877
    cria uma nova função a partir


    da composição de funções e
    elimina valores intermediários
    Passo 2
    aplicação parcial da função map
    a composição é feita da


    direita para a esquerda

    View Slide

  83. / /
    shopping cart


    const cart = [


    {id: 1, product: 'iPhone', price: 499},


    {id: 2, product: 'Kindle', price: 179},


    {id: 3, product: 'Macbook Pro', price: 1199},


    ];


    / /
    get prices from shopping cart and sum them


    / /
    using function composition with pipe


    const totalCart = R.pipe(


    R.map(item
    = >
    item.price),


    R.sum,


    );


    console.log(totalCart(cart));
    / /
    1877
    Passo 3
    o pipe de funções é feito da
    esquerda para a direita e
    facilita a leitura do código

    View Slide

  84. Caso de Uso 2


    limpar dados vindo de um formulário e
    realizar um cálculo

    View Slide

  85. / /
    cleaning data from an input


    const price = '100';


    const discount = (perc, value)
    = >
    perc * value;


    let priceInt = parseInt(price);


    let priceDiscount = discount(0.2, priceInt);


    console.log(priceDiscount);
    / /
    20
    Passo 1

    View Slide

  86. / /
    cleaning data from an input


    const price = '100';


    const discount = (perc, value)
    = >
    perc * value;


    / /
    using partial application


    const discount20 = R.partial(discount, [0.2]);


    let priceInt = parseInt(price);


    let priceDiscount = discount20(priceInt);


    console.log(priceDiscount);
    / /
    20
    Passo 2
    cria uma nova função a partir da


    aplicação parcial de uma existente

    View Slide

  87. / /
    cleaning data from an input


    const price = '100';


    const discount = (perc, value)
    = >
    perc * value;


    / /
    using function composition


    const priceDiscount = R.pipe(


    parseInt,


    R.partial(discount, [0.2]),


    );


    console.log(priceDiscount(price));
    / /
    20
    Passo 3
    cria uma nova função a partir


    da composição de funções
    utilizando a função pipe e
    elimina valores intermediários

    View Slide

  88. / /
    cleaning data from an input


    const price = 'lambda!';


    const discount = (perc, value)
    = >
    perc * value;


    / /
    using function composition


    const priceDiscount = R.pipe(


    parseInt,


    R.partial(discount, [0.2]),


    );


    console.log(priceDiscount(price));
    / /
    null
    Passo 4
    erro ao receber um valor


    não numérico

    View Slide

  89. / /
    cleaning data from an input


    const price = 'lambda!';


    const discount = (perc, value)
    = >
    perc * value;


    / /
    using function composition


    const priceDiscount = R.pipe(


    parseInt,


    R.defaultTo(0),


    R.partial(discount, [0.2]),


    );


    console.log(priceDiscount(price));
    / /
    0
    Passo 5
    retorna o valor padrão para o
    caso de um valor não truthy

    View Slide

  90. Outras


    Bibliotecas
    λ

    View Slide

  91. 1. RxJS

    2. Lodash

    3. Immutable.js

    4. HyperApp
    outras bibliotecas

    View Slide

  92. Conclusão

    View Slide

  93. a programação funcional não é sobre não
    ter estado…

    View Slide

  94. …e sim sobre eliminar estado e efeito
    colateral sempre que possível e controlar
    efeitos colaterais quando necessário

    View Slide

  95. existem inúmeros conceitos relacionados a
    programação funcional como functors,
    mônades, lazy evaluation, lens, tail call
    optimization…

    View Slide

  96. vá em frente e divirta-se!

    View Slide

  97. Referências

    View Slide

  98. 1. Mostly Adequate Guide

    2. Functional-Light JavaScript

    3. Ramda Docs

    4. JavaScript Funcional - Arthur Xavier
    referências

    View Slide

  99. Avalie!

    View Slide

  100. @marcelgsantos
    speakerdeck.com/marcelgsantos
    Obrigado.
    Perguntas?

    View Slide