Programmation fonctionnelle en PHP : niveau avancé
\n\nLa programmation fonctionnelle (PF) est un paradigme dans lequel les calculs sont considérés comme l'évaluation de fonctions mathématiques, et où les changements d'état et les données mutables sont évités. Bien que PHP n'ait pas été initialement conçu comme un langage purement fonctionnel, à partir de la version 7.4 et surtout en PHP 8.x, il a reçu des outils puissants pour écrire du code dans un style fonctionnel. Dans cet article, nous allons explorer les concepts avancés de la PF en PHP : des fonctions d'ordre supérieur aux monades, avec des exemples pratiques et des recommandations.
\n\n1. Fonctions d'ordre supérieur et fermetures
\n\nLes fonctions d'ordre supérieur sont des fonctions qui acceptent d'autres fonctions comme arguments ou qui les retournent. En PHP, cela est implémenté via des fonctions anonymes (fermetures) et les fonctions intégrées array_map, array_filter, array_reduce.
Exemple : fonction de rappel pour le filtrage
\n\n<?php\n$numbers = [1, 2, 3, 4, 5, 6];\n\n// Fonction d'ordre supérieur\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// Fonction anonyme prédicat\n$isEven = fn($n) => $n % 2 === 0;\n\n$evenNumbers = $filterEven($numbers, $isEven);\n// Résultat : [2, 4, 6]\nprint_r($evenNumbers);\n?>\n\n\nExemple : fabrique de fonctions (fermeture avec état)
\n\n<?php\nfunction createMultiplier(float $factor): callable {\n // La fermeture "se souvient" 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\nLes fermetures en PHP permettent de capturer des variables de la portée externe via use (en PHP 7.4+, on peut utiliser les fonctions fléchées fn). C'est la base pour construire la curryfication et l'application partielle.
2. Curryfication et application partielle
\n\nLa curryfication est la transformation d'une fonction à plusieurs arguments en une séquence de fonctions à un seul argument. L'application partielle est la fixation d'une partie des arguments d'une fonction. PHP n'a pas de support intégré, mais cela se implémente facilement.
\n\nExemple : curryfication manuelle
\n\n<?php\n// Fonction normale\nfunction add(int $a, int $b): int {\n return $a + $b;\n}\n\n// Version curryfiée\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\nExemple : fonction universelle de curryfication
\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\nLa curryfication est particulièrement utile pour la composition de fonctions et la création de versions spécialisées de fonctions générales.
\n\n3. Composition de fonctions et patrons fonctionnels
\n\nLa composition de fonctions est la création d'une nouvelle fonction en appliquant successivement plusieurs fonctions. Le résultat d'une fonction est passé en entrée à la suivante.
\n\nExemple : composition "de gauche à droite" (pipe)