المولدات في PHP

من موسوعة حسوب
< PHP
مراجعة 03:42، 4 أبريل 2018 بواسطة عبد اللطيف ايمش (نقاش | مساهمات) (استبدال النص - 'PHP\/Function\/([^|]*)' ب'PHP/$1')

تقدّم المولِّدات (Generators) طريقة سهلة لاستخدام المكرِّرات (Iterators) البسيطة دون الدخول في تعقيدات استخدام صنف يطبّق الواجهة Iterator.

تتيح المولِّدات كتابة شيفرة تستخدم foreach لمرور على مجموعة من البيانات دون الحاجة إلى بناء مصفوفة في الذاكرة مما قد يؤدي إلى تجاوز حدود الذاكرة، أو يحتاج إلى وقت معالجة طويل لإنشائه. بدلًا من ذلك، يمكن كتابة دالة مولِّدة وهي دالة مشابهة للدوال الاعتيادية باستثناء أنّها لا تعيد النتيجة مرة واحدة بل تعيد العدد المطلوب من النتائج لغرض تقديم القيم التي يتم المرور عليها.

ومن أبسط الأمثلة على المولِّدات هو إعادة استخدام الدالة range()‎ كمولِّد. تنشئ الدالة range()‎ الاعتيادية مصفوفة تتضمن جميع القيم وتعيدها وقد ينتج عن ذلك مصفوفة كبيرة جدًّا، فعلى سبيل المثال استدعاء الدالة range(0, 1000000)‎ يستهلك ما يقارب 100 MB من الذاكرة.

يمكن استبدال الدالة الاعتيادية بالدالة المولدة xrange()‎‎، والتي تحتاج إلى كمية مقبولة من الذاكرة لإنشاء كائن Iterator وتتبع حالة المولّد الحالية داخليًا، وكلّ ذلك يستهل أقل من 1 كيلوبايت.

المثال 1: استخدام الدالة range()‎ كدالة مولّدة

لاحظ أنّ كلتا الدالتين range()‎ و xrange()‎ تعطيان المخرجات ذاتها.

<?php
function xrange($start, $limit, $step = 1) {
    if ($start < $limit) {
        if ($step <= 0) {
            throw new LogicException('Step must be +ve');
        }

        for ($i = $start; $i <= $limit; $i += $step) {
            yield $i;
        }
    } else {
        if ($step >= 0) {
            throw new LogicException('Step must be -ve');
        }

        for ($i = $start; $i >= $limit; $i += $step) {
            yield $i;
        }
    }
}

echo 'Single digit odd numbers from range():  ';
foreach (range(1, 9, 2) as $number) {
    echo "$number ";
}
echo "\n";

echo 'Single digit odd numbers from xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
    echo "$number ";
}
?>

يعطي المثال السابق المخرجات التالية:

Single digit odd numbers from range():  1 3 5 7 9 
Single digit odd numbers from xrange(): 1 3 5 7 9

كائنات Generator

عند استدعاء الدالة المولِّدة للمرة الأولى تعيد الدالة كائنًا من الصنف الداخلي Generator. يطبّق هذا الكائن واجهة Iterator بنفس الطريقة التي يتبعها كائن iterator الموجّه للإمام فقط، ويقدّم التوابع التي يمكن استدعاءها لمعالجة حالة المولِّد، ومنها إرسال القيم إلى المولِّد واستقبالها منه.

صيغة المولدات

الدالة المولدة مشابهة تمامًا للدالة الاعتيادية، باستثناء أنّ الدالة المولدة تنتج (yield) قيمًا حسب الحاجة بدلًا من إعادة قيمة واحدة.

تعيد الدالة المولّدة عند استدعائها كائنًا يمكن المرور على عناصره، وعند القيام بذلك (باستخدام حلقة foreach مثلًا) فإنّ PHP ستستدعي الدالة المولدة في كل مرة تحتاج فيها إلى قيمة، ثم تحفظ حالة الدالة المولدة عندما تنتج قيمة وهكذا يمكن الرجوع إلى تلك الحالة عند الحاجة إلى القيمة اللاحقة.

مقارنة المولّدات بكائنات Iterator

إن الميزة الأساسية التي تتمتّع بها المولّدات هي بساطتها، إذ أنّ الشيفرة المطلوبة أقل بكثير مقارنة باستخدام صنف Iterator، وتكون ذات مقروئية أعلى.

مصادر