البرمجة الوظيفية في PHP: المستوى المتقدم
\n\nالبرمجة الوظيفية (FP) هي نموذج يتم فيه التعامل مع العمليات الحسابية كحساب دوال رياضية، مع تجنب تغيير الحالة والبيانات القابلة للتغيير. على الرغم من أن PHP لم تُصمم في الأصل كلغة وظيفية بحتة، إلا أنها بدءًا من الإصدار 7.4 وخاصة في PHP 8.x، حصلت على أدوات قوية لكتابة الكود بأسلوب وظيفي. في هذه المقالة، سنستعرض المفاهيم المتقدمة للبرمجة الوظيفية في PHP: من دوال الترتيب الأعلى إلى المونادات، مع أمثلة عملية وتوصيات.
\n\n1. دوال الترتيب الأعلى والإغلاقات
\n\nدوال الترتيب الأعلى هي دوال تقبل دوال أخرى كوسائط أو تُرجعها. في PHP، يتم تحقيق ذلك من خلال الدوال المجهولة (الإغلاقات) والدوال المضمنة array_map، array_filter، array_reduce.
مثال: دالة رد اتصال للتصفية
\n\n<?php\n$numbers = [1, 2, 3, 4, 5, 6];\n\n// دالة ترتيب أعلى\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// دالة مجهولة (مسند)\n$isEven = fn($n) => $n % 2 === 0;\n\n$evenNumbers = $filterEven($numbers, $isEven);\n// النتيجة: [2, 4, 6]\nprint_r($evenNumbers);\n?>\n\n\nمثال: مصنع الدوال (إغلاق مع حالة)
\n\n<?php\nfunction createMultiplier(float $factor): callable {\n // الإغلاق "يتذكر" $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\nتسمح الإغلاقات في PHP بالتقاط المتغيرات من النطاق الخارجي عبر use (في PHP 7.4+ يمكن استخدام دوال الأسهم fn). هذا هو الأساس لبناء الكاري والتطبيق الجزئي.
2. الكاري والتطبيق الجزئي
\n\nالكاري هو تحويل دالة تأخذ عدة وسائط إلى سلسلة من الدوال التي تأخذ وسيطًا واحدًا. التطبيق الجزئي هو تثبيت جزء من وسائط الدالة. لا يحتوي PHP على دعم مدمج، ولكن من السهل تنفيذه.
\n\nمثال: الكاري اليدوي
\n\n<?php\n// دالة عادية\nfunction add(int $a, int $b): int {\n return $a + $b;\n}\n\n// النسخة المُكَرّاة\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\nمثال: دالة كاري عامة
\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\nالكاري مفيد بشكل خاص في تركيب الدوال وإنشاء إصدارات متخصصة من الدوال العامة.
\n\n3. تركيب الدوال والأنماط الوظيفية
\n\nتركيب الدوال هو إنشاء دالة جديدة من خلال تطبيق عدة دوال بشكل متسلسل. يتم تمرير نتيجة دالة واحدة كمدخل للدالة التالية.
\n\nمثال: التركيب "من اليسار إلى اليمين" (pipe)