Programação Funcional em PHP: Nível Avançado
\n\nProgramação Funcional (PF) é um paradigma no qual os cálculos são tratados como avaliação de funções matemáticas, e a mudança de estado e dados mutáveis são evitados. Embora o PHP não tenha sido originalmente projetado como uma linguagem puramente funcional, a partir da versão 7.4 e especialmente no PHP 8.x, ele ganhou ferramentas poderosas para escrever código em estilo funcional. Neste artigo, abordaremos conceitos avançados de PF em PHP: desde funções de alta ordem até mônadas, com exemplos práticos e recomendações.
\n\n1. Funções de alta ordem e closures
\n\nFunções de alta ordem são funções que recebem outras funções como argumentos ou as retornam. Em PHP, isso é implementado através de funções anônimas (closures) e funções embutidas como array_map, array_filter, array_reduce.
Exemplo: função de callback para filtragem
\n\n<?php\n$numbers = [1, 2, 3, 4, 5, 6];\n\n// Função de alta ordem\n$filterEven = function(array $items, callable $callback): array {\n $result = [];\n foreach ($items as $item) {\n if ($callback($item)) {\n $result[] = $item;\n }\n }\n return $result;\n};\n\n// Função anônima predicado\n$isEven = fn($n) => $n % 2 === 0;\n\n$evenNumbers = $filterEven($numbers, $isEven);\n// Resultado: [2, 4, 6]\nprint_r($evenNumbers);\n?>\n\n\nExemplo: fábrica de funções (closure com estado)
\n\n<?php\nfunction createMultiplier(float $factor): callable {\n // A closure "lembra" de $factor\n return fn($number) => $number * $factor;\n}\n\n$double = createMultiplier(2);\n$triple = createMultiplier(3);\n\necho $double(5); // 10\necho $triple(5); // 15\n?>\n\n\nClosures em PHP permitem capturar variáveis do escopo externo através de use (no PHP 7.4+ é possível usar funções arrow fn). Esta é a base para construir currying e aplicação parcial.
2. Currying e aplicação parcial
\n\nCurrying é a transformação de uma função de vários argumentos em uma sequência de funções de um argumento. Aplicação parcial é a fixação de parte dos argumentos de uma função. O PHP não tem suporte nativo, mas isso é fácil de implementar.
\n\nExemplo: currying manual
\n\n<?php\n// Função comum\nfunction add(int $a, int $b): int {\n return $a + $b;\n}\n\n// Versão curried\n$curriedAdd = function(int $a): callable {\n return function(int $b) use ($a): int {\n return $a + $b;\n };\n};\n\n$addFive = $curriedAdd(5);\necho $addFive(3); // 8\n?>\n\n\nExemplo: função universal de currying
\n\n<?php\nfunction curry(callable $fn, int $arity = null): callable {\n $reflection = new ReflectionFunction($fn);\n $arity = $arity ?? $reflection->getNumberOfRequiredParameters();\n\n $curry = function(...$args) use ($fn, $arity, &$curry) {\n if (count($args) >= $arity) {\n return $fn(...$args);\n }\n return function(...$nextArgs) use ($fn, $args, $arity, $curry) {\n return $curry(...array_merge($args, $nextArgs));\n };\n };\n\n return $curry;\n}\n\n$add = function(int $a, int $b, int $c): int {\n return $a + $b + $c;\n};\n\n$curriedAdd = curry($add);\n$result = $curriedAdd(1)(2)(3); // 6\necho $result;\n?>\n\n\nCurrying é especialmente útil na composição de funções e na criação de versões especializadas de funções genéricas.
\n\n3. Composição de funções e padrões funcionais
\n\nComposição de funções é a criação de uma nova função através da aplicação sequencial de várias funções. O resultado de uma função é passado como entrada para a próxima.
\n\nExemplo: composição "da esquerda para a direita" (pipe)