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

Programação Funcional em PHP: saia da zona de conforto

Programação Funcional em PHP: saia da zona de conforto

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 (funções de primeira classe, alta ordem e puras, estados, imutabilidade e recursão), programação funcional em PHP, map, filter e reduce, funções parciais, memoization e currying, composição, bibliotecas em PHP, vantagens e desvantagens.

Marcel dos Santos

September 21, 2019
Tweet

More Decks by Marcel dos Santos

Other Decks in Programming

Transcript

  1. Programação
    Funcional em PHP
    saia da zona de conforto
    Marcel Gonçalves dos Santos
    @marcelgsantos
    λ

    View Slide

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

    View Slide

  3. View Slide

  4. @femugsp
    sp.femug.com

    View Slide

  5. @phpsp
    phpsp.org.br

    View Slide

  6. Learning OOP in PHP
    Tutoriais, vídeos, slides, livros sobre OOP, OOD,
    design patterns, refatoração e arquitetura.
    bit.ly/Learning-OOP-in-PHP

    View Slide

  7. 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

  8. 1. seguir @marcelgsantos no Twitter

    2. tuitar utilizando as hashtags #phpmgconf,

    #funcional e #php

    3. não vale tuíte em branco e retuíte

    4. ler e preencher este simples formulário

    bit.ly/sorteio-phpmg
    Concorra a um livro da Casa do Código!

    View Slide

  9. O que é programação
    funcional?

    View Slide

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

    View Slide

  11. O que é paradigma de
    programação?

    View Slide

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

    View Slide

  13. Os paradigmas de programação definem como os
    códigos são estruturados.

    View Slide

  14. principais paradigmas de programação

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

    View Slide

  15. paradigma imperativo

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

    View Slide

  16. paradigma imperativo

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

    View Slide

  17. !// Imperative code to sum 1 to 10

    $sum = 0;
    for ($i = 1; $i !<= 10; $i!++) {
    $sum += $i;
    }
    print $sum; !// 55

    View Slide

  18. paradigma declarativo

    permite especificar o que deve ser
    computado e não como deve ser computado

    View Slide

  19. paradigma declarativo

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

    View Slide

  20. !// Declarative code to sum 1 to 10
    print array_sum(range(1, 10)); !// 55

    View Slide

  21. paradigmas de linguagens de programação


    imperativo

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


    declarativo

    lógico - Prolog
    funcional - Clojure, Elixir, Elm, Erlang, F#, Haskell, Lisp, OCaml e Scala

    View Slide

  22. Programação

    Funcional
    λ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  26. Uma função matemática trata-se de um simples
    mapeamento entre o domínio e o contra-domínio.
    1
    2
    3
    D
    B
    A
    C
    X Y

    View Slide

  27. Estado
    λ

    View Slide

  28. o estado de um programa é representado
    pelos valores dos dados armazenados na
    memória…

    View Slide

  29. …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 ou pelo
    próprio sistema…

    View Slide

  31. …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. funções puras


    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

    View Slide

  35. !// pure or impure function?
    $counter = 0;
    $increment = function () use (&$counter) {
    $counter!++;
    return $counter;
    };
    print $increment(); !// 1

    View Slide

  36. !// pure function
    function add($x, $y) {
    return $x + $y;
    }
    print add(2, 3); !// 5

    View Slide

  37. !// pure function using closure syntax
    $add = function ($x, $y) {
    return $x + $y;
    };
    print $add(2, 3); !// 5

    View Slide

  38. !// pure function using arrow function

    !// syntax (PHP 7.4)
    $add = fn($x, $y) !=> $x + $y;
    print $add(2, 3); !// 5

    View Slide

  39. 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

  40. 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

  41. !// referential transparency
    $add = fn($x, $y) !=> $x + $y;
    var_dump($add(2, 3) !!=== 5); !// true
    var_dump(5 !!=== 5); !// true

    View Slide

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

    View Slide

  43. porém, a restritividade ajuda a melhorar o
    foco

    View Slide

  44. Mais sobre

    Funções
    λ

    View Slide

  45. funções de primeira classe

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

    View Slide

  46. !// first-class function
    $add = fn($x, $y) !=> $x + $y;
    $numbers = [1, 2, 3, 4, 5];
    $sum = array_reduce($numbers, $add);
    $sum10 = array_reduce($numbers, $add, 10);
    print $sum; !// 15
    print $sum10; !// 25

    View Slide

  47. !// first-class function
    $add = fn($x, $y) !=> $x + $y;
    $numbers = [1, 2, 3, 4, 5];
    $sum = array_reduce($numbers, $add);
    $sum10 = array_reduce($numbers, $add, 10);
    print $sum; !// 15
    print $sum10; !// 25

    View Slide

  48. funções de alta ordem

    são funções que operam sobre outras
    funções

    View Slide

  49. !// high-order function
    $add = fn($x, $y) !=> $x + $y;
    $numbers = [1, 2, 3, 4, 5];
    $sum = array_reduce($numbers, $add);
    $sum10 = array_reduce($numbers, $add, 10);
    print $sum; !// 15
    print $sum10; !// 25

    View Slide

  50. !// high-order function
    $add = fn($x, $y) !=> $x + $y;
    $numbers = [1, 2, 3, 4, 5];
    $sum = array_reduce($numbers, $add);
    $sum10 = array_reduce($numbers, $add, 10);
    print $sum; !// 15
    print $sum10; !// 25

    View Slide

  51. Os conceitos de funções de primeira classe e funções
    de alta ordem estão intimamente relacionados, uma
    não existiria sem a outra.

    View Slide

  52. funções anônimas

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

    View Slide

  53. !// anonymous function
    $numbers = [1, 2, 3, 4, 5];
    $sum = array_reduce($numbers, fn($x, $y) !=> $x + $y);
    print $sum; !// 15

    View Slide

  54. escopo

    uma função lambda ou função anônima tem
    o seu próprio escopo como qualquer função
    no PHP

    View Slide

  55. escopo

    o escopo é tratado de forma diferente entre
    as linguagens JavaScript e PHP

    View Slide

  56. escopo

    no JavaScript uma função anônima pode
    acessar uma variável do escopo externo
    enquanto no PHP isto não é permitido

    View Slide

  57. closures

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

    View Slide

  58. !// closure function
    function greet($greeting) {
    return function ($name) use ($greeting) {
    return "$greeting $name!";
    };
    }
    $greet = fn($greeting) !=> fn($name) !=> "$greeting $name!";
    print greet('Hello')('Mary'); !// Hello Mary!
    print $greet('Hello')('Mary'); !// Hello Mary!

    View Slide

  59. closures

    as closures em PHP utilizam a abordagem
    early-binding, ou seja, as variáveis da
    closure terão os valores que tinham quando
    a closure foi definida

    View Slide

  60. closures

    isso pode ser sobrescrito utilizando
    passagem por referência ou redefinindo
    uma closure

    View Slide

  61. funções como objetos

    no PHP as funções são consideradas objetos

    View Slide

  62. !// function as object
    class Hello {
    public function !__invoke($name) {
    return "Hello $name!";
    }
    }
    $hello = new Hello;
    print $hello('John'); !// Hello John!
    a classe deve implementar
    o método __invoke

    View Slide

  63. recursão

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

    View Slide

  64. !// recursive function
    function factorial($number) {
    if ($number !!=== 1) {
    return 1;
    } else {
    return ($number * factorial($number - 1));
    }
    }
    print factorial(5); !// 120

    View Slide

  65. !// recursive function (using closure syntax)
    $factorial = function ($number) use (&$factorial) {
    if ($number !!=== 1) {
    return 1;
    } else {
    return ($number * $factorial($number - 1));
    }
    };
    print $factorial(5); !// 120

    View Slide

  66. 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

  67. “Don't think of functions as a collection of
    instructions. Think of them as non-destructive
    operations on input `double = n => n * 2;`”
    Eric Elliott, 2016.
    https:/
    /twitter.com/_ericelliott/status/685172918784004097

    View Slide

  68. memoize

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

    View Slide

  69. !// expensive cost function memoized
    $factorial = $memoize(function ($number) use (&$factorial) {
    sleep(1); !// it takes 1s to run!
    if ($number !!=== 1) {
    return 1;
    } else {
    return ($number * $factorial($number - 1));
    }
    });
    print $factorial(5); !// 120 (after 5s)
    print $factorial(7); !// 5040 (after 2s)

    View Slide

  70. Imutabilidade
    λ

    View Slide

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

    View Slide

  72. a imutabilidade permite maior confiança e
    evita que erros ocorram

    View Slide

  73. o PHP não possui suporte completo a dados
    imutáveis de forma nativa

    View Slide

  74. porém, algumas técnicas como value
    objects podem ser utilizadas para alcançar a
    imutabilidade

    View Slide

  75. Currying e

    Aplicação Parcial
    λ

    View Slide

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

    View Slide

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

    View Slide

  78. !// uncurried function

    function greet($greeting, $name) {
    return "$greeting $name";
    }
    print greet('Good morning', 'Alice'); !// Good morning Alice
    $greetMorning = greet('Good morning');
    !// PHP Fatal error: Uncaught ArgumentCountError: Too
    !// few arguments to function greet(), 1 passed

    View Slide

  79. !// "curried" function
    function greet($greeting) {
    return function ($name) use ($greeting) {
    return "$greeting $name";
    };
    }
    $greetMorning = greet('Good morning');
    print $greetMorning('Alice'); !// Good morning Alice
    print greet('Good morning')('Alice'); !// Good morning Alice
    print greet('Good morning', 'Alice'); !// error!

    View Slide

  80. !// "curried" function using arrow function (PHP 7.4)
    $greet = fn($greeting) !=> fn($name) !=> "$greeting $name!";
    $greetMorning = $greet('Good morning');
    print $greetMorning('Alice'); !// Good morning Alice
    print $greet('Good morning')('Alice'); !// Good morning Alice
    print $greet('Good morning', 'Alice'); !// error!

    View Slide

  81. !// curried function using Functional library
    $greet = curry(function ($greeting, $name) {
    return "$greeting $name";
    });
    print $greet('Good morning')('Alice'); !// Good morning Alice
    print $greet('Good morning', 'Alice'); !// Good morning Alice

    View Slide

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

    View Slide

  83. !// using a helper function that allows to perform
    !// partial application in a regular not curried function
    $add = function ($x, $y) {
    return $x + $y;
    };
    $add3 = partial($add, 3);
    print $add3(2); !// 5

    View Slide

  84. a aplicação parcial permite fazer a
    especialização de uma função mais genérica

    View Slide

  85. !// specialization from a curried function
    !// using partial application
    $greet = curry(function ($greeting, $name) {
    return "$greeting $name";
    });

    $greetMorning = $greet('Good morning');
    print $greetMorning('Alice'); !// Good morning Alice

    View Slide

  86. !// specialization from a curried function
    !// using partial application (PHP 7.4)
    $greet = curry(fn($greeting, $name) !=> "$greeting $name");

    $greetMorning = $greet('Good morning');
    print $greetMorning('Alice'); !// Good morning Alice

    View Slide

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

    View Slide

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

    View Slide

  89. os parâmetros mais genéricos devem vir
    mais para o início e os parâmetros mais
    específicos devem vir mais para o final

    View Slide

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

    View Slide

  91. Composição

    de Funções
    λ

    View Slide

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

    View Slide

  93. !// create a function using composition (traditional way)
    $sentence = 'estava à toa na vida o meu amor me chamou pra
    ver a banda passar cantando coisas de amor';

    $wordCount = function ($text) {
    return count(explode(' ', $text));
    };
    print $wordCount($sentence); !// 19

    View Slide

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

    View Slide

  95. a biblioteca Functional possui uma função
    que permite criar uma nova função a partir
    da composição de funções

    View Slide

  96. !// create a function using composition
    $sentence = 'estava à toa na vida o meu amor me chamou pra
    ver a banda passar cantando coisas de amor';
    $wordCount = compose(partial('explode', ' '), 'count');
    print $wordCount($sentence); !// 19

    View Slide

  97. Diferenças 

    entre OO e FP
    λ

    View Slide

  98. um objeto possui características,
    comportamentos e estado atual e realiza
    operações sobre o seu próprio estado

    View Slide

  99. uma função não faz alterações diretas no
    estado e, sim, retorna novas transformações
    do estado atual

    View Slide

  100. Caso de 

    Uso
    λ

    View Slide

  101. Caso de Uso 1

    somar os preços dos produtos de um
    carrinho de compra

    View Slide

  102. !// shopping cart
    $cart = [
    ['id' !=> 1, 'product' !=> 'iPhone', 'price' !=> 499],
    ['id' !=> 2, 'product' !=> 'Kindle', 'price' !=> 179],
    ['id' !=> 3, 'product' !=> 'MacBook Pro', 'price' !=> 1199],
    ];
    $total = 0;
    !// get price from shopping cart and sum them
    !// imperative way (using for-loop and accumulator)
    for ($i = 0; $i < count($cart); $i!++) {
    $total += $cart[$i]['price'];
    }
    print $total; !// 1877
    Passo 1

    View Slide

  103. !// shopping cart
    $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
    !// functional way (intermediate values)
    $cartPrices = map(fn($item) !=> $item['price'], $cart);
    $total = sum($cartPrices);
    print $total; !// 1877
    Passo 2
    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

    View Slide

  104. !// shopping cart
    $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
    !// functional way (functional composition)
    $totalCart = compose(
    map(fn($item) !=> $item['price']),
    'f\sum'
    );
    print $totalCart($cart); !// 1877
    Passo 3
    cria uma nova função a partir
    da composição de funções e
    elimina valores intermediários
    aplicação parcial da função map

    View Slide

  105. Outras

    Bibliotecas
    λ

    View Slide

  106. bibliotecas


    1. lstrojny/functional-php

    2. kapolos/pramda

    3. sergiors/prelude

    4. widmogrod/php-functional

    5. nikic/iter

    6. leocavalcante/siler

    7. ihor/Nspl
    "
    "

    View Slide

  107. Conclusão
    λ

    View Slide

  108. as linguagens de programação tradicionais
    têm adotado conceitos de programação
    funcional logo é importante conhecê-los

    View Slide

  109. por mais que o PHP não tenha um suporte
    amplo a programação funcional o mindset
    funcional te ajudará a se tornar um(a)
    programador(a) melhor

    View Slide

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

    View Slide

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

    View Slide

  112. foque na transformação do estado e evite
    efeitos colaterais

    View Slide

  113. conhecer bem os paradigmas de
    programação te permite escolher a melhor
    ferramenta para cada problema

    View Slide

  114. A programação funcional garante o que é
    código bom em outros paradigmas.

    View Slide

  115. existem inúmeros conceitos relacionados a
    programação funcional como functors,
    monads, lazy evaluation, tail call
    optimization…

    View Slide

  116. vá em frente e divirta-se!

    View Slide

  117. Referências

    View Slide

  118. Getting Started with FP in PHP
    Tutoriais, vídeos, slides, bibliotecas, pessoas
    influentes sobre programação funcional em PHP.
    bit.ly/Getting-Started-with-FP-in-PHP

    View Slide

  119. Avalie!

    View Slide

  120. bit.ly/avalie-palestra-php-funcional

    View Slide

  121. Anúncio!

    View Slide

  122. bit.ly/workshop-php74
    Informações: será apresentado um histórico breve da linguagem, as
    principais funcionalidades do PHP 7.4 de forma prática como typed
    properties, arrow functions, spread operator, preloading, FFI entre
    outras e funcionalidades futuras do PHP 8.0.

    View Slide

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

    View Slide