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

Programação Funcional em PHP (edição 2025)

Programação Funcional em PHP (edição 2025)

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.

Avatar for Marcel dos Santos

Marcel dos Santos

December 12, 2025
Tweet

More Decks by Marcel dos Santos

Other Decks in Programming

Transcript

  1. 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 - utilize as hashtags #php, #phpconferencebrasil e #programacaofuncional
  2. 1. seguir @marcelgsantos no LinkedIn 2. fazer publicação sobre o

    curso com as hashtags #php, #phpconferencebrasil e #programacaofuncional 3. me marcar na publicação 4. marcar a PHP Conference Brasil 5. não vale publicação em branco Concorra a um livro da Casa do Código! 🤩 LinkedIn
  3. Os p ar adigmas de pro gr amação definem c

    om o os códigos são es tr ut ur ados.
  4. Paradigma imperativo Descreve a resolução de um problema através de

    comandos que o computador pode compreender e executar.
  5. / / código imperativo para somar de 1 a 10

    $sum = 0; for ($i = 1; $i < = 10; $i + + ) { $sum += $i; } print $sum; / / 55
  6. Paradigma declarativo Permite especi fi car o que deve ser

    computado e não como deve ser computado.
  7. / / código declarativo para somar de 1 a 10

    print array_sum(range(1, 10)); / / 55
  8. 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
  9. Matemático e lógico que criou o cálculo lambda, a base

    teórica da programação funcional e um dos pilares da computação moderna.
  10. 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
  11. O estado de um programa é representado pelo valor dos

    dados armazenados na memória em qualquer ponto de execução.
  12. O estado de uma aplicação é alterado a cada interação

    feita pelo usuário ou pelo próprio sistema…
  13. 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
  14. / / função pura ou impura? $counter = 0; $increment

    = function () use (&$counter) { $counter + + ; return $counter; }; print $increment(); / / 1
  15. / / função pura (closure) $add = function ($x, $y)

    { return $x + $y; }; print $add(2, 3); / / 5
  16. / / função pura (arrow function) $add = fn($x, $y)

    = > $x + $y; print $add(2, 3); / / 5
  17. 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.
  18. / / transparência referencial $add = fn($x, $y) = >

    $x + $y; var_dump($add(2, 3) = = = 5); / / true var_dump(5 = = = 5); / / true
  19. 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.
  20. / / função de primeira classe $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
  21. / / função de primeira classe $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
  22. / / função de alta ordem $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
  23. / / função de alta ordem $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
  24. Os c on ceitos de funções de prime ir a

    classe e funções de alta or dem estão intimamente relaci on ados, uma não ex ist ir ia sem a outr a.
  25. Funções anônimas São funções que não possuem nome e que,

    geralmente, são passadas como argumento ou atribuídas.
  26. / / função anônima $numbers = [1, 2, 3, 4,

    5]; $sum = array_reduce($numbers, fn($x, $y) = > $x + $y); print $sum; / / 15
  27. Escopo Uma função lambda ou função anônima tem o seu

    próprio escopo como qualquer função no PHP.
  28. Escopo No JavaScript uma função anônima pode acessar uma variável

    do escopo externo enquanto no PHP isto não é permitido.
  29. / / função closure 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!
  30. 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 de fi nida.
  31. / / função como objeto class Hello { public function

    _ _ invoke($name) { return "Hello $name!"; } } $hello = new Hello; print $hello('John'); / / Hello John!
  32. First-Class Callable Syntax É uma nova sintaxe mais expressiva para

    criar um callable a partir do escopo atual.
  33. First-Class Callable Syntax A nova sintaxe reduz o boilerplate de

    código e é mais acessível a ferramentas de análise estática.
  34. / / f i rst - class callable syntax $fn

    = strtoupper( . . . ); / / $fn = Closure : : fromCallable('strtoupper'); echo $fn('hello'); / / HELLO
  35. / / f i rst - class callable syntax $list

    = ['hello', 'hola', 'hallo']; $output = array_map(strtoupper( . . . ), $list); print_r($output); / / ['HELLO', 'HOLA', 'HALLO']
  36. Pipe Operator É um operador que envia o resultado de

    uma expressão como primeiro argumento para a próxima função.
  37. Pipe Operator Ele permite criar pipelines de transformação mais claros

    e legíveis igual ao pipe do Elixir, F# e Hack.
  38. / / pipe operator $raw = " John Doe ";

    $result = $raw | > trim( . . . ) | > strtolower( . . . ) | > (fn($x) = > preg_replace('/\s + /', '-', $x)); echo $result; / / john - doe
  39. Recursão É quando uma função é de fi nida em

    termos de si própria, ou seja, quando a função chama ela mesma.
  40. / / função recursiva function factorial($number) { if ($number =

    = = 1) { return 1; } else { return ($number * factorial($number - 1)); } } print factorial(5); / / 120
  41. / / função recursiva (usando a sintaxe de closure) $factorial

    = function ($number) use (&$factorial) { if ($number = = = 1) { return 1; } else { return ($number * $factorial($number - 1)); } }; print $factorial(5); / / 120
  42. 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.
  43. “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 oper ati on s on input `d ou ble = n => n * 2;`” - Eric Ellio tt , 2016.
  44. / / função de alto custo memoizada $factorial = $memoize(function

    ($number) use (&$factorial) { sleep(1); / / leva 1s para executar! if ($number = = = 1) { return 1; } else { return ($number * $factorial($number - 1)); } }); print $factorial(5); / / 120 (depois de 5s) print $factorial(7); / / 5040 (depois de 2s)
  45. …em uma função que recebe apenas um argumento e que

    retorna uma função que aceita os argumentos restantes.
  46. / / função não "curried" 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
  47. / / função "curried" 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!
  48. / / função "curried" usando arrow function $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!
  49. / / função "curried" usando a biblioteca Functional $greet =

    curry(function ($greeting, $name) { return "$greeting $name"; }); print $greet('Good morning')('Alice'); / / Good morning Alice print $greet('Good morning', 'Alice'); / / Good morning Alice
  50. A aplicação parcial é quando se executa uma função e

    passa apenas parte de seus argumentos.
  51. / / usa uma função helper para permitir realizar a

    / / aplicação parcial em uma função comum não curried $add = function ($x, $y) { return $x + $y; }; $add3 = partial($add, 3); print $add3(2); / / 5
  52. / / especialização de uma função "curried" / / usando

    aplicação parcial $greet = curry(function ($greeting, $name) { return "$greeting $name"; }); $greetMorning = $greet('Good morning'); print $greetMorning('Alice'); / / Good morning Alice
  53. / / especialização de uma função "curried" / / usando

    aplicação parcial (arrow function) $greet = curry(fn($greeting, $name) = > "$greeting $name"); $greetMorning = $greet('Good morning'); print $greetMorning('Alice'); / / Good morning Alice
  54. 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.
  55. O PHP não possui suporte nativo para currying como nas

    linguagens puramente funcionais Elm ou Haskell.
  56. O suporte nativo para aplicação parcial foi aprovado com unanimidade

    e estará disponível na versão 8.6 da linguagem.
  57. / / aplicação parcial (a partir do PHP 8.6) function

    add4(int $a, int $b, int $c, int $d) : int { return $a + $b + $c + $d; } $fn = add4(1, ?, 3, 4); / / $fn = static fn(int $b) : int = > add4(1, $b, 3, 4); echo $fn(2); / / 1 + 2 + 3 + 4 = 10
  58. A composição é o processo de combinar uma ou mais

    funções para criar uma nova função.
  59. / / cria uma função usando composição (maneira tradicional) $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
  60. É uma solução elegante e legível e ajuda a evitar

    a utilização do aninhamento de funções.
  61. A biblioteca Functional possui uma função que permite criar uma

    nova função a partir da composição de funções.
  62. / / cria uma função usando composição $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
  63. Uma função não faz alterações diretas no estado e, sim,

    retorna novas transformações do estado atual.
  64. / / carrinho de compras $cart = [ ['id' =

    > 1, 'product' = > 'iPhone', 'price' = > 499], ['id' = > 2, 'product' = > 'Kindle', 'price' = > 179], ['id' = > 3, 'product' = > 'MacBook Pro', 'price' = > 1199], ]; $total = 0; / / obtém os preços do carrinho de compras e realiza a soma / / abordagem imperativa (usando for - loop e acumuladores) for ($i = 0; $i < count($cart); $i + + ) { $total += $cart[$i]['price']; } print $total; / / 1877
  65. / / carrinho de compras $cart = [ ['id' =

    > 1, 'product' = > 'iPhone', 'price' = > 499], ['id' = > 2, 'product' = > 'Kindle', 'price' = > 179], ['id' = > 3, 'product' = > 'MacBook Pro', 'price' = > 1199], ]; / / obtém os preços do carrinho de compras e realiza a soma / / abordagem funcional (usando valores intermediários) $cartPrices = array_map(fn($item) = > $item['price'], $cart); $total = array_sum($cartPrices); print $total; / / 1877
  66. / / carrinho de compras $cart = [ ['id' =

    > 1, 'product' = > 'iPhone', 'price' = > 499], ['id' = > 2, 'product' = > 'Kindle', 'price' = > 179], ['id' = > 3, 'product' = > 'MacBook Pro', 'price' = > 1199], ]; / / obtém os preços do carrinho de compras e realiza a soma / / abordagem funcional (usando composição de funções) $totalCart = compose( array_map(fn ($item) = > $item['price'], ?), array_sum( . . . ) ); print $totalCart($cart); / / 1877
  67. Bibliotecas 1. lstrojny/functional-php (7 milhões) 2. widmogrod/php-functional (5,9 milhões) 3.

    nikic/iter (5,5 milhões) 4. functional-php/fantasy-land (5,5 milhões) 5. lambdish/phunctional (1,8 milhões) 6. crell/fp (350 mil) 7. fp4php/functional (200 mil)
  68. O PHP adotou, nos últimos anos, diversas funcionalidades de programação

    funcional como a sintaxe fi rst-class callable, o pipe operator e a aplicação parcial.
  69. Por mais que o PHP não tenha um suporte completo

    a programação funcional, o mindset funcional te ajudará a se tornar um(a) programador(a) melhor.
  70. …e sim sobre eliminar estado e efeito colateral sempre que

    possível e controlar efeitos colaterais quando necessário.
  71. A pro gr amação funci on al g ar ante

    o que é código b o em outr os p ar adigmas.