الفرق بين المراجعتين لصفحة: «Ruby/calling methods»
تصحيح تنسيق الأكواد |
جميل-بيلوني (نقاش | مساهمات) طلا ملخص تعديل |
||
(1 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE: استدعاء التوابع في روبي}}</noinclude> | |||
عندما تستدعي تابعًا، فإنّك تمرّر رسالة لكائن معيّن لأجل تنفيذ مهمّة معيّنة، ويتمّ ذلك في لغة روبي كالتّالي:<syntaxhighlight lang="ruby"> | |||
عندما تستدعي تابعًا، فإنّك تمرّر رسالة لكائن معيّن لأجل تنفيذ مهمّة معيّنة، ويتمّ ذلك في لغة روبي كالتّالي: | |||
<syntaxhighlight lang="ruby"> | |||
my_method() | my_method() | ||
</syntaxhighlight> | </syntaxhighlight>لاحظ أنّ استخدام الأقواس المنحنية هنا اختياريّ:<syntaxhighlight lang="ruby"> | ||
لاحظ أنّ استخدام الأقواس المنحنية هنا اختياريّ: | |||
<syntaxhighlight lang="ruby"> | |||
my_method | my_method | ||
</syntaxhighlight> | </syntaxhighlight>المعتمد في هذا التّوثيق أن تُستخدّم الأقواس عند وجود المعامِلات لإزالة الالتباس، إلا في حالة وجود فرق بين وجود الأقواس وحذفها. | ||
المعتمد في هذا التّوثيق أن تُستخدّم الأقواس عند وجود المعامِلات لإزالة الالتباس، إلا في حالة وجود فرق بين وجود الأقواس وحذفها. | |||
هذا القسم يغطّي فقط كيفيّة استدعاء التوابع، وستُشرَح كيفيّة تعريف التّوابع في قسم آخر. | هذا القسم يغطّي فقط كيفيّة استدعاء التوابع، وستُشرَح كيفيّة [[Ruby/methods|تعريف التّوابع]] في قسم آخر. | ||
==المستقبِل== | |||
== المستقبِل == | المستقبِل (Receiver) الافتراضي في لغة روبي هو <code>self</code> وهو الذي يُستخدَم في حال عدم تحديد أيّ مستقبل آخر. ولأجل تحديد مستقبِل، يستَدعى التابع بالشّكل التالي:<syntaxhighlight lang="ruby"> | ||
المستقبِل الافتراضي في لغة روبي هو self وهو الذي يُستخدَم في حال عدم تحديد أيّ مستقبل آخر. ولأجل تحديد | |||
<syntaxhighlight lang="ruby"> | |||
my_object.my_method | my_object.my_method | ||
</syntaxhighlight> | </syntaxhighlight>في هذه الحالة تُرسل رسالة <code>my_method</code> إلى الكائن <code>my_object</code>. فكلّ كائن يمكنه أن يكون مستقبِلًا لتابع ما؛ لكن حتى يتمّ ذلك، يجب أن يكون التابع مرئيًّا لهذا الكائن، وإلّا فسيظهر خطأ من نوع <code>[[Ruby/NoMethodError|NoMethodError]]</code>. | ||
في هذه الحالة تُرسل رسالة my_method إلى الكائن my_object. فكلّ كائن يمكنه أن يكون مستقبِلًا لتابع | |||
يمكنك استخدام & | يمكنك استخدام المعامل <code>.&</code> (متبوعًا بنقطة) لتعيّن <code>&</code> كمستقبل، حينها لن يُنفّذ التابع <code>my_method</code>، وستكون النتيجة <code>nil</code> عندما يكون المستقبِل <code>nil</code>، ولن تُقيَّم معامِلات التّابع <code>my_method</code> في هذه الحالة. | ||
كما يمكنك استخدام :: لتعيين المستقبل، لكنّ هذه الطريقة نادرة الاستخدام لأنّها قد تسبّب التباسًا مع الرمز :: المستخدم في مجالات الأسماء (namespaces). | كما يمكنك استخدام <code>::</code> لتعيين المستقبل، لكنّ هذه الطريقة نادرة الاستخدام لأنّها قد تسبّب التباسًا مع الرمز <code>::</code> المستخدم في مجالات الأسماء (namespaces). | ||
==الوسائط== | |||
تدعم لغة روبي ثلاثة أنواع من الوسائط (arguments) التي يمكن تمريرها عند إرسال الرسائل وهي: الوسائط الموضعية، ووسائط القيم المفتاحية (أوالوسائط المسماة [named arguments])، ووسائط الكتلة البرمجية. كل رسالة تُرسَل تستخدم نوعًا أو اثنين أو كل هذه الأنواع، إلّا أنّها إذا استُخدمت معًا، فيجب أن تكون ضمن هذا الترتيب نفسه. | |||
كلّ الوسائط في لغة روبي تُمرّر مرجعيًا ولا يؤجّل تقييمها. تفصل الوسائط بالفاصلة <code>,</code> بالشكل التالي:<syntaxhighlight lang="ruby"> | |||
كلّ | |||
<syntaxhighlight lang="ruby"> | |||
my_method(1, '2', :three) | my_method(1, '2', :three) | ||
</syntaxhighlight> | </syntaxhighlight>يُمكن أن تكون الوسائط على شكل تعبير برمجي [[Ruby/Hash|كالجدول Hash]]:<syntaxhighlight lang="ruby"> | ||
يُمكن أن تكون | |||
<syntaxhighlight lang="ruby"> | |||
'key' => value | 'key' => value | ||
</syntaxhighlight> | </syntaxhighlight>أو وسائط مسماة (Keyword arguments):<syntaxhighlight lang="ruby"> | ||
أو | |||
<syntaxhighlight lang="ruby"> | |||
key: value | key: value | ||
</syntaxhighlight> | </syntaxhighlight>[[Ruby/Hash|الجداول Hash]] والوسائط المسماة يجب أن تكون متجاورة ويجب أن تتلو الوسائط الموضعيّة، ولا بأس في أن تُخلط فيما بينها:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
my_method('a' => 1, b: 2, 'c' => 3) | my_method('a' => 1, b: 2, 'c' => 3) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== | ==الوسائط الموضعيّة== | ||
تتبع الوسائط الموضعيّة (Positional Arguments) للرسالة اسم التابع مباشرة:<syntaxhighlight lang="ruby"> | |||
<syntaxhighlight lang="ruby"> | |||
my_method(argument1, argument2) | my_method(argument1, argument2) | ||
</syntaxhighlight> | </syntaxhighlight>في كثير من الحالات، لا تكون الأقواس ضروريّة عند إرسال الرسالة:<syntaxhighlight lang="ruby"> | ||
في كثير من | |||
<syntaxhighlight lang="ruby"> | |||
my_method argument1, argument2 | my_method argument1, argument2 | ||
</syntaxhighlight> | </syntaxhighlight>لكنّها ضروريّة لإزالة الالتباس، فالمثال التّالي سيسبب خطأً في صيغة (<code>[[Ruby/SyntaxError|SyntaxError]]</code>) بسبب أنّ مفسّر لغة روبي لن يعرف إلى من يجب إرسال الوسيط الثالث <code>argument3</code>:<syntaxhighlight lang="ruby"> | ||
لكنّها ضروريّة لإزالة الالتباس، فالمثال التّالي سيسبب | |||
<syntaxhighlight lang="ruby"> | |||
method_one argument1, method_two argument2, argument3 | method_one argument1, method_two argument2, argument3 | ||
</syntaxhighlight> | </syntaxhighlight>إذا احتوى تعريف التابع على وسيط مبدوء برمز <code>*</code>، فالوسائط الموضعيّة الإضافيّة ستُسنَد إلى هذا الوسيط في التابع على هيئة مصفوفة. | ||
إذا احتوى تعريف التابع على | |||
إذا لم يحتوِ تعريف التابع على | إذا لم يحتوِ تعريف التابع على وسائط مسماة، فإنّ أيّة وسائط مسماة أو الوسائط ذات [[Ruby/Hash|النوع Hash]] ستُسند جميعها [[Ruby/Hash|كجدول Hash]] واحد إلى آخر وسيط في تعريف التابع:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method(options) | def my_method(options) | ||
p options | p options | ||
end | end | ||
my_method('a' => 1, b: 2) # تطبع: {'a'=>1, :b=>2} | my_method('a' => 1, b: 2) # تطبع: {'a'=>1, :b=>2} | ||
</syntaxhighlight> | </syntaxhighlight>إذا مُرر عدد كبير من الوسائط الموضعية، فسيسبب ذلك ظهور الخطأ <code>[[Ruby/ArgumentError|ArgumentError]]</code>. | ||
إذا مُرر عدد كبير من | ==الوسائط الموضعية الافتراضية== | ||
عندما تعرَّف وسائط افتراضية في تعريف التابع، فلست بحاجة إلى تزويده بكل الوسائط عند الاستدعاء، فالمفسّر سيملأ المعاملات الناقصة وفق الترتيب. | |||
ففي أبسط الحالات، عندما تكون الوسائط الافتراضية هي الأخيرة في أقصى اليمين مثل:<syntaxhighlight lang="ruby"> | |||
ففي أبسط | |||
<syntaxhighlight lang="ruby"> | |||
def my_method(a, b, c = 3, d = 4) | def my_method(a, b, c = 3, d = 4) | ||
p [a, b, c, d] | p [a, b, c, d] | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>لكلّ من المعاملين <code>c</code> و <code>d</code> قيمة افتراضية، فإذا مُرِّر معاملين فقط في استدعاء التابع مثل:<syntaxhighlight lang="ruby"> | ||
لكلّ من المعاملين c و d قيمة افتراضية، فإذا | |||
<syntaxhighlight lang="ruby"> | |||
my_method(1, 2) | my_method(1, 2) | ||
</syntaxhighlight> | </syntaxhighlight>فستكون النتيجة كالتالي:<syntaxhighlight lang="text"> | ||
فستكون النتيجة كالتالي: | |||
<syntaxhighlight lang="text"> | |||
[1, 2, 3, 4] | [1, 2, 3, 4] | ||
</syntaxhighlight> | </syntaxhighlight>وإذا مرّرت ثلاثة معاملات:<syntaxhighlight lang="ruby"> | ||
وإذا مرّرت ثلاثة معاملات: | |||
<syntaxhighlight lang="ruby"> | |||
my_method(1, 2, 5) | my_method(1, 2, 5) | ||
</syntaxhighlight> | </syntaxhighlight>فستكون النتيجة:<syntaxhighlight lang="text"> | ||
فستكون النتيجة | |||
<syntaxhighlight lang="text"> | |||
[1, 2, 5, 4] | [1, 2, 5, 4] | ||
</syntaxhighlight> | </syntaxhighlight>حيث يملأ مفسّر روبي المعاملات النّاقصة من اليسار إلى اليمين. | ||
حيث يملأ مفسّر | |||
تسمح لغة روبي بأن توضع | تسمح لغة روبي بأن توضع الوسائط الافتراضية في المنتصف بين الوسائط الموضعية الأخرى. لنأخذ هذا المثال الأكثر تعقيدًا: <syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method(a, b = 2, c = 3, d) | def my_method(a, b = 2, c = 3, d) | ||
p [a, b, c, d] | p [a, b, c, d] | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>هنا <code>b</code> و <code>c</code> يأخذان قيمًا افتراضيّة. فإذا مُرِّر معاملين فقط في استدعاء التابع بالشكل:<syntaxhighlight lang="ruby"> | ||
هنا b و c يأخذان قيمًا افتراضيّة. فإذا | |||
<syntaxhighlight lang="ruby"> | |||
my_method(1, 4) | my_method(1, 4) | ||
</syntaxhighlight> | </syntaxhighlight>ستكون النتيجة:<syntaxhighlight lang="text"> | ||
ستكون النتيجة: | |||
<syntaxhighlight lang="text"> | |||
[1, 2, 3, 4] | [1, 2, 3, 4] | ||
</syntaxhighlight> | </syntaxhighlight>وإذا مُرِّر ثلاثة معاملات:<syntaxhighlight lang="ruby"> | ||
وإذا | |||
<syntaxhighlight lang="ruby"> | |||
my_method(1, 5, 6) | my_method(1, 5, 6) | ||
</syntaxhighlight> | </syntaxhighlight>ستكون النتيجة:<syntaxhighlight lang="text"> | ||
ستكون النتيجة: | |||
<syntaxhighlight lang="text"> | |||
[1, 5, 3, 6] | [1, 5, 3, 6] | ||
</syntaxhighlight> | </syntaxhighlight>من الصّعب وصف الذي يحصل هنا بالكلمات، لذلك سنشرحها باستخدام المتغيّرات وقيمها. | ||
من الصّعب وصف الذي يحصل هنا بالكلمات، لذلك سنشرحها باستخدام المتغيّرات وقيمها. | |||
بداية تُسند القيمة 1 إلى | بداية تُسند القيمة 1 إلى <code>a</code>، ثمّ تسند القيمة 6 إلى <code>d</code>. وهكذا يبقى المعاملَين ذوَي القيمة الافتراضية. وطالما أنّ القيمة 5 لم تُسنَد بعد، فستعطى إلى <code>b</code>، ويحصل <code>c</code> على القيمة الافتراضية 3. | ||
== | ==الوسائط المسماة== | ||
الوسائط المسماة تلي الوسائط الموضعية ويفصل بينها فواصل:<syntaxhighlight lang="ruby"> | |||
<syntaxhighlight lang="ruby"> | |||
my_method(positional1, keyword1: value1, keyword2: value2) | my_method(positional1, keyword1: value1, keyword2: value2) | ||
</syntaxhighlight> | </syntaxhighlight>إذا لم تظهر الوسائط المسماة عند استدعاء التابع رغم وجودها في تعريفه، فستأخذ القيمة الافتراضيّة المعرّفة فيه. أمّا إذا مُرّرت هذه الوسائط في الاستدعاء دون أن يحتوي عليها تعريف التّابع، فسيظهر حينئذ الخطأ <code>[[Ruby/ArgumentError|ArgumentError]]</code>. | ||
إذا لم تظهر | ==وسائط الكتل البرمجية== | ||
== | وسائط الكتل البرمجيّة تمرّر كتلة برمجيّة من النّطاق الذي يستدعي التّابع، ويكون ترتيب هذه الوسائط دائمًا في نهاية الوسائط الممرّرة للتابع. وتُمرّر الكتلة البرمجيّة باستخدام <code>do.. end</code> أو الأقواس <code>{..}</code>:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
my_method do | my_method do | ||
# ... | # ... | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>أو:<syntaxhighlight lang="ruby"> | ||
أو: | |||
<syntaxhighlight lang="ruby"> | |||
my_method { | my_method { | ||
# ... | # ... | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight>تأخذ <code>do-end</code> أولويّة أدنى من القوسين <code>{}</code> المعقوصين؛ ففي المثال التّالي:<syntaxhighlight lang="ruby"> | ||
تأخذ do-end أولويّة أدنى من {} | |||
<syntaxhighlight lang="ruby"> | |||
method_1 method_2 { | method_1 method_2 { | ||
# ... | # ... | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight>تُرسل الكتلة البرمجيّة إلى التابع <code>method_2</code>؛ بينما في المثال:<syntaxhighlight lang="ruby"> | ||
تُرسل الكتلة البرمجيّة إلى التابع | |||
<syntaxhighlight lang="ruby"> | |||
method_1 method_2 do | method_1 method_2 do | ||
# ... | # ... | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>ترسل الكتلة إلى التابع <code>method_1</code>. | ||
ترسل الكتلة إلى التابع method_1. | |||
يمكن أن تستقبل الكتلة البرمجية | يمكن أن تستقبل الكتلة البرمجية وسائط من التابع المرسلة له. هذه الوسائط تعرّف بطريقة مشابهة لطريقة تعريفها في التوابع، وتمرّر ضمن <code>|...|</code> بعد كلمة <code>do</code> أو القوس المفتتح للكتلة:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
my_method do |argument1, argument2| | my_method do |argument1, argument2| | ||
# ... | # ... | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== | ==الوسائط المحلية للكتلة البرمجية== | ||
يمكنك أيضًا تعريف | يمكنك أيضًا تعريف وسائط محليّة على مستوى الكتلة البرمجيّة باستخدام الرّمز <code>;</code> في قائمة وسائط الكتلة. لاحظ أنّ إسناد قيم إلى هذه الوسائط ليس له أيّ تأثير على المتغيّرات المحليّة التي لها نفس الاسم والموجودة خارج هذه الكتلة في النطاق الذي يستدعي التابع:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method | def my_method | ||
yield self | yield self | ||
سطر 167: | سطر 113: | ||
end | end | ||
puts "place is: #{place}" | puts "place is: #{place}" | ||
</syntaxhighlight> | </syntaxhighlight>وتكون النتيجة:<syntaxhighlight lang="text"> | ||
وتكون النتيجة: | |||
<syntaxhighlight lang="text"> | |||
hello main this is block | hello main this is block | ||
place is world | place is world | ||
</syntaxhighlight> | </syntaxhighlight>فالمتغيّر <code>place</code> ضمن الكتلة الممرّرة إلى التابع ليس نفسه المتغيّر <code>place</code> خارجها، وبالمقابل لو حذفنا <code>place ;</code> من وسائط الكتلة، فستكون النتيجة:<syntaxhighlight lang="text"> | ||
فالمتغيّر place ضمن الكتلة الممرّرة إلى التابع ليس نفسه المتغيّر place خارجها، وبالمقابل لو حذفنا ; | |||
<syntaxhighlight lang="text"> | |||
hello main this is block | hello main this is block | ||
place is block | place is block | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== التحويل من مصفوفة إلى | ==التحويل من مصفوفة إلى وسائط== | ||
ليكن لدينا هذا التابع: | ليكن لدينا هذا التابع:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method(argument1, argument2, argument3) | def my_method(argument1, argument2, argument3) | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>يمكنك تحويل مصفوفة إلى سلسلة من الوسائط عن طريق تمرير المصفوفة مسبوقة برمز النجمة <code>*</code> (المسمى بمعامل الفصل):<syntaxhighlight lang="ruby"> | ||
يمكنك تحويل مصفوفة إلى سلسلة من | |||
<syntaxhighlight lang="ruby"> | |||
arguments = [1, 2, 3] | arguments = [1, 2, 3] | ||
my_method(*arguments) | my_method(*arguments) | ||
</syntaxhighlight> | </syntaxhighlight>أو:<syntaxhighlight lang="ruby"> | ||
أو: | |||
<syntaxhighlight lang="ruby"> | |||
arguments = [2, 3] | arguments = [2, 3] | ||
my_method(1, *arguments) | my_method(1, *arguments) | ||
</syntaxhighlight> | </syntaxhighlight>كلاهما مكافئ لما يلي:<syntaxhighlight lang="ruby"> | ||
كلاهما مكافئ لما يلي: | |||
<syntaxhighlight lang="ruby"> | |||
my_method(1, 2, 3) | my_method(1, 2, 3) | ||
</syntaxhighlight> | </syntaxhighlight>في حالة كان التابع يستقبل وسائط مسماة، فاستخدام معامل الفصل حينها سيحوّل [[Ruby/Hash|الجدول Hash]] الموجود في نهاية المصفوفة إلى وسائط مسماة:<syntaxhighlight lang="ruby"> | ||
في حالة | |||
<syntaxhighlight lang="ruby"> | |||
def my_method(a, b, c: 3) | def my_method(a, b, c: 3) | ||
end | end | ||
arguments = [1, 2, { c: 4 }] | arguments = [1, 2, { c: 4 }] | ||
my_method(*arguments) | my_method(*arguments) | ||
</syntaxhighlight> | </syntaxhighlight>يمكنك أيضًا استخدام الرمز <code>**</code> (سيأتي شرحه لاحقًا) لتحوّل عناصر [[Ruby/Hash|الجدول Hash]] إلى وسائط مسماة. | ||
يمكنك أيضًا استخدام الرمز ** (سيأتي شرحه لاحقًا) لتحوّل | |||
إذا لم يطابق عددُ الكائنات في المصفوفة عددَ المعاملات في | إذا لم يطابق عددُ الكائنات في المصفوفة عددَ المعاملات في التابع، فسيظهر الخطأ <code>[[Ruby/ArgumentError|ArgumentError]]</code>. | ||
وإذا جاء معامل الفصل في بداية | |||
== التحويل من | وإذا جاء معامل الفصل في بداية الوسائط عند الاستدعاء، فيجب استخدام الأقواس عندها منعًا لظهور تحذير (warning). | ||
لنأخذ هذا التابع على سبيل المثال: | ==التحويل من جدول Hash إلى وسائط مسماة== | ||
<syntaxhighlight lang="ruby"> | لنأخذ هذا التابع على سبيل المثال:<syntaxhighlight lang="ruby"> | ||
def my_method(first: 1, second: 2, third: 3) | def my_method(first: 1, second: 2, third: 3) | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>يمكنك تحويل محتوى [[Ruby/Hash|الجدول Hash]] إلى وسائط مسماة باستخدام المعامل <code>**</code>:<syntaxhighlight lang="ruby"> | ||
يمكنك تحويل | |||
<syntaxhighlight lang="ruby"> | |||
arguments = { first: 3, second: 4, third: 5 } | arguments = { first: 3, second: 4, third: 5 } | ||
my_method(**arguments) | my_method(**arguments) | ||
</syntaxhighlight> | </syntaxhighlight>أو:<syntaxhighlight lang="ruby"> | ||
أو: | |||
<syntaxhighlight lang="ruby"> | |||
arguments = { first: 3, second: 4 } | arguments = { first: 3, second: 4 } | ||
my_method(third: 5, **arguments) | my_method(third: 5, **arguments) | ||
</syntaxhighlight> | </syntaxhighlight>كلاهما مكافئ لما يلي:<syntaxhighlight lang="ruby"> | ||
كلاهما مكافئ لما يلي: | |||
<syntaxhighlight lang="ruby"> | |||
my_method(first: 3, second: 4, third: 5) | my_method(first: 3, second: 4, third: 5) | ||
</syntaxhighlight> | </syntaxhighlight>استخدم المعامل <code>**</code> في تعريف التابع لتجمّع الوسائط المسماة أيًا كانت، إذ أنّها لن تُجمّع باستخدام المعامل <code>*</code>:<syntaxhighlight lang="ruby"> | ||
استخدم ** في تعريف التابع لتجمّع | |||
<syntaxhighlight lang="ruby"> | |||
def my_method(*a, **kw) | def my_method(*a, **kw) | ||
p arguments: a, keywords: kw | p arguments: a, keywords: kw | ||
end | end | ||
my_method(1, 2, '3' => 4, five: 6) | my_method(1, 2, '3' => 4, five: 6) | ||
</syntaxhighlight> | </syntaxhighlight>وتكون النتيجة:<syntaxhighlight lang="text"> | ||
وتكون النتيجة: | |||
<syntaxhighlight lang="text"> | |||
{:arguments=>[1, 2, {"3"=>4}], :keywords=>{:five=>6}} | {:arguments=>[1, 2, {"3"=>4}], :keywords=>{:five=>6}} | ||
</syntaxhighlight> | </syntaxhighlight>على عكس معامل الفصل الموضّح سابقًا، فإنّ المعامل <code>**</code> ليس له اسم معيّن متعارف عليه. | ||
على عكس معامل الفصل الموضّح | ==التحويل من الكائنات <code>Proc</code> إلى كتل برمجية== | ||
== التحويل من | لنأخذ التابع التالي على سبيل المثال:<syntaxhighlight lang="ruby"> | ||
لنأخذ التابع التالي على سبيل المثال: | |||
<syntaxhighlight lang="ruby"> | |||
def my_method | def my_method | ||
yield self | yield self | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>يمكنك تحويل كائن من النوع <code>[[Ruby/Proc|proc]]</code> أو <code>lambda</code> إلى كتلة برمجيّة باستخدام المعامل <code>&</code>:<syntaxhighlight lang="ruby"> | ||
يمكنك تحويل كائن من | |||
<syntaxhighlight lang="ruby"> | |||
argument = proc { |a| puts "#{a.inspect} was yielded" } | argument = proc { |a| puts "#{a.inspect} was yielded" } | ||
my_method(&argument) | my_method(&argument) | ||
</syntaxhighlight> | </syntaxhighlight>إذا سبق في الاستدعاء معامل الفصل <code>*</code>، فيجب حينها استخدام الاقواس منعًا لظهور تحذير. | ||
إذا سبق في الاستدعاء معامل الفصل * فيجب حينها استخدام الاقواس منعًا لظهور تحذير. | |||
وكما هو الحال بالنّسبة للمعامل ** فإنّ المعامل & أيضًا ليس له اسم معيّن متعارف عليه. | وكما هو الحال بالنّسبة للمعامل <code>**</code>، فإنّ المعامل <code>&</code> أيضًا ليس له اسم معيّن متعارف عليه. | ||
== البحث عن التوابع == | ==البحث عن التوابع== | ||
عندما ترسل | عندما ترسل رسالة، فإنّ مفسر روبي يبحث عن التابع الذي يطابق اسم مستقبل الرسالة؛ هذه التّوابع مخزّنة في [[:تصنيف:Ruby Class|أصناف]] (classes) و<nowiki/>[[:تصنيف:Ruby Module|وحدات]] (modules) يمرّ المفسّر عليها أثناء عمليّة البحث، ولا يبحث في كائناتها. | ||
هذا هو الترتيب المتّبع في عمليّة البحث عن | |||
* وحدات R السابقة بترتيب عكسيّ. | هذا هو الترتيب المتّبع في عمليّة البحث عن تابع للصنف أو الوحدة R الخاصّ بمستقبل معين: | ||
* تابع مطابق في R | *وحدات R السابقة بترتيب عكسيّ. | ||
* الوحدات المتضمّنة في R بترتيب عكسيّ | *تابع مطابق في R. | ||
وإذا كان للصنفّ R صنف أب (superclass) فستكرّر العمليّة في الصنف الأب حتى | *الوحدات المتضمّنة في R بترتيب عكسيّ. | ||
وإذا لم يُعثر على أيّ | وإذا كان للصنفّ R صنف أب (superclass)، فستكرّر العمليّة في الصنف الأب حتى يُعثَر على التابع، وتتوقّف عمليّة البحث متى عُثر على التابع. | ||
عند تفعيل ميزة التحسينات | |||
== مصادر == | وإذا لم يُعثر على أيّ نتيجة، فستعاد العمليّة من البداية لكن بالبحث عن <code>method_missing</code>، والتابع الافتراضيّ له <code>BasicObject.method_missing</code> والذي يسبّب ظهور الخطأ <code>[[Ruby/NameError|NameError]]</code> عندما يستدعى. | ||
* [https://ruby-doc.org/core-2.5.1/doc/syntax/calling_methods_rdoc.html صفحة Calling Methods في توثيق روبي الرسمي.] | |||
عند تفعيل ميزة [[Ruby/refinements|التحسينات]] الاختبارية، فسيتغيّر ترتيب البحث عن التوابع، اقرأ توثيق [[Ruby/refinements|التحسينات]] لمزيد من التفاصيل. | |||
==مصادر== | |||
*[https://ruby-doc.org/core-2.5.1/doc/syntax/calling_methods_rdoc.html صفحة Calling Methods في توثيق روبي الرسمي.] | |||
[[تصنيف: Ruby]] | |||
[[تصنيف: Ruby Syntax]] |
المراجعة الحالية بتاريخ 06:21، 19 نوفمبر 2018
عندما تستدعي تابعًا، فإنّك تمرّر رسالة لكائن معيّن لأجل تنفيذ مهمّة معيّنة، ويتمّ ذلك في لغة روبي كالتّالي:
my_method()
لاحظ أنّ استخدام الأقواس المنحنية هنا اختياريّ:
my_method
المعتمد في هذا التّوثيق أن تُستخدّم الأقواس عند وجود المعامِلات لإزالة الالتباس، إلا في حالة وجود فرق بين وجود الأقواس وحذفها.
هذا القسم يغطّي فقط كيفيّة استدعاء التوابع، وستُشرَح كيفيّة تعريف التّوابع في قسم آخر.
المستقبِل
المستقبِل (Receiver) الافتراضي في لغة روبي هو self
وهو الذي يُستخدَم في حال عدم تحديد أيّ مستقبل آخر. ولأجل تحديد مستقبِل، يستَدعى التابع بالشّكل التالي:
my_object.my_method
في هذه الحالة تُرسل رسالة my_method
إلى الكائن my_object
. فكلّ كائن يمكنه أن يكون مستقبِلًا لتابع ما؛ لكن حتى يتمّ ذلك، يجب أن يكون التابع مرئيًّا لهذا الكائن، وإلّا فسيظهر خطأ من نوع NoMethodError
.
يمكنك استخدام المعامل .&
(متبوعًا بنقطة) لتعيّن &
كمستقبل، حينها لن يُنفّذ التابع my_method
، وستكون النتيجة nil
عندما يكون المستقبِل nil
، ولن تُقيَّم معامِلات التّابع my_method
في هذه الحالة.
كما يمكنك استخدام ::
لتعيين المستقبل، لكنّ هذه الطريقة نادرة الاستخدام لأنّها قد تسبّب التباسًا مع الرمز ::
المستخدم في مجالات الأسماء (namespaces).
الوسائط
تدعم لغة روبي ثلاثة أنواع من الوسائط (arguments) التي يمكن تمريرها عند إرسال الرسائل وهي: الوسائط الموضعية، ووسائط القيم المفتاحية (أوالوسائط المسماة [named arguments])، ووسائط الكتلة البرمجية. كل رسالة تُرسَل تستخدم نوعًا أو اثنين أو كل هذه الأنواع، إلّا أنّها إذا استُخدمت معًا، فيجب أن تكون ضمن هذا الترتيب نفسه.
كلّ الوسائط في لغة روبي تُمرّر مرجعيًا ولا يؤجّل تقييمها. تفصل الوسائط بالفاصلة ,
بالشكل التالي:
my_method(1, '2', :three)
يُمكن أن تكون الوسائط على شكل تعبير برمجي كالجدول Hash:
'key' => value
أو وسائط مسماة (Keyword arguments):
key: value
الجداول Hash والوسائط المسماة يجب أن تكون متجاورة ويجب أن تتلو الوسائط الموضعيّة، ولا بأس في أن تُخلط فيما بينها:
my_method('a' => 1, b: 2, 'c' => 3)
الوسائط الموضعيّة
تتبع الوسائط الموضعيّة (Positional Arguments) للرسالة اسم التابع مباشرة:
my_method(argument1, argument2)
في كثير من الحالات، لا تكون الأقواس ضروريّة عند إرسال الرسالة:
my_method argument1, argument2
لكنّها ضروريّة لإزالة الالتباس، فالمثال التّالي سيسبب خطأً في صيغة (SyntaxError
) بسبب أنّ مفسّر لغة روبي لن يعرف إلى من يجب إرسال الوسيط الثالث argument3
:
method_one argument1, method_two argument2, argument3
إذا احتوى تعريف التابع على وسيط مبدوء برمز *
، فالوسائط الموضعيّة الإضافيّة ستُسنَد إلى هذا الوسيط في التابع على هيئة مصفوفة.
إذا لم يحتوِ تعريف التابع على وسائط مسماة، فإنّ أيّة وسائط مسماة أو الوسائط ذات النوع Hash ستُسند جميعها كجدول Hash واحد إلى آخر وسيط في تعريف التابع:
def my_method(options)
p options
end
my_method('a' => 1, b: 2) # تطبع: {'a'=>1, :b=>2}
إذا مُرر عدد كبير من الوسائط الموضعية، فسيسبب ذلك ظهور الخطأ ArgumentError
.
الوسائط الموضعية الافتراضية
عندما تعرَّف وسائط افتراضية في تعريف التابع، فلست بحاجة إلى تزويده بكل الوسائط عند الاستدعاء، فالمفسّر سيملأ المعاملات الناقصة وفق الترتيب.
ففي أبسط الحالات، عندما تكون الوسائط الافتراضية هي الأخيرة في أقصى اليمين مثل:
def my_method(a, b, c = 3, d = 4)
p [a, b, c, d]
end
لكلّ من المعاملين c
و d
قيمة افتراضية، فإذا مُرِّر معاملين فقط في استدعاء التابع مثل:
my_method(1, 2)
فستكون النتيجة كالتالي:
[1, 2, 3, 4]
وإذا مرّرت ثلاثة معاملات:
my_method(1, 2, 5)
فستكون النتيجة:
[1, 2, 5, 4]
حيث يملأ مفسّر روبي المعاملات النّاقصة من اليسار إلى اليمين. تسمح لغة روبي بأن توضع الوسائط الافتراضية في المنتصف بين الوسائط الموضعية الأخرى. لنأخذ هذا المثال الأكثر تعقيدًا:
def my_method(a, b = 2, c = 3, d)
p [a, b, c, d]
end
هنا b
و c
يأخذان قيمًا افتراضيّة. فإذا مُرِّر معاملين فقط في استدعاء التابع بالشكل:
my_method(1, 4)
ستكون النتيجة:
[1, 2, 3, 4]
وإذا مُرِّر ثلاثة معاملات:
my_method(1, 5, 6)
ستكون النتيجة:
[1, 5, 3, 6]
من الصّعب وصف الذي يحصل هنا بالكلمات، لذلك سنشرحها باستخدام المتغيّرات وقيمها.
بداية تُسند القيمة 1 إلى a
، ثمّ تسند القيمة 6 إلى d
. وهكذا يبقى المعاملَين ذوَي القيمة الافتراضية. وطالما أنّ القيمة 5 لم تُسنَد بعد، فستعطى إلى b
، ويحصل c
على القيمة الافتراضية 3.
الوسائط المسماة
الوسائط المسماة تلي الوسائط الموضعية ويفصل بينها فواصل:
my_method(positional1, keyword1: value1, keyword2: value2)
إذا لم تظهر الوسائط المسماة عند استدعاء التابع رغم وجودها في تعريفه، فستأخذ القيمة الافتراضيّة المعرّفة فيه. أمّا إذا مُرّرت هذه الوسائط في الاستدعاء دون أن يحتوي عليها تعريف التّابع، فسيظهر حينئذ الخطأ ArgumentError
.
وسائط الكتل البرمجية
وسائط الكتل البرمجيّة تمرّر كتلة برمجيّة من النّطاق الذي يستدعي التّابع، ويكون ترتيب هذه الوسائط دائمًا في نهاية الوسائط الممرّرة للتابع. وتُمرّر الكتلة البرمجيّة باستخدام do.. end
أو الأقواس {..}
:
my_method do
# ...
end
أو:
my_method {
# ...
}
تأخذ do-end
أولويّة أدنى من القوسين {}
المعقوصين؛ ففي المثال التّالي:
method_1 method_2 {
# ...
}
تُرسل الكتلة البرمجيّة إلى التابع method_2
؛ بينما في المثال:
method_1 method_2 do
# ...
end
ترسل الكتلة إلى التابع method_1
.
يمكن أن تستقبل الكتلة البرمجية وسائط من التابع المرسلة له. هذه الوسائط تعرّف بطريقة مشابهة لطريقة تعريفها في التوابع، وتمرّر ضمن |...|
بعد كلمة do
أو القوس المفتتح للكتلة:
my_method do |argument1, argument2|
# ...
end
الوسائط المحلية للكتلة البرمجية
يمكنك أيضًا تعريف وسائط محليّة على مستوى الكتلة البرمجيّة باستخدام الرّمز ;
في قائمة وسائط الكتلة. لاحظ أنّ إسناد قيم إلى هذه الوسائط ليس له أيّ تأثير على المتغيّرات المحليّة التي لها نفس الاسم والموجودة خارج هذه الكتلة في النطاق الذي يستدعي التابع:
def my_method
yield self
end
place = "world"
my_method do |obj; place|
place = "block"
puts "hello #{obj} this is #{place}"
end
puts "place is: #{place}"
وتكون النتيجة:
hello main this is block
place is world
فالمتغيّر place
ضمن الكتلة الممرّرة إلى التابع ليس نفسه المتغيّر place
خارجها، وبالمقابل لو حذفنا place ;
من وسائط الكتلة، فستكون النتيجة:
hello main this is block
place is block
التحويل من مصفوفة إلى وسائط
ليكن لدينا هذا التابع:
def my_method(argument1, argument2, argument3)
end
يمكنك تحويل مصفوفة إلى سلسلة من الوسائط عن طريق تمرير المصفوفة مسبوقة برمز النجمة *
(المسمى بمعامل الفصل):
arguments = [1, 2, 3]
my_method(*arguments)
أو:
arguments = [2, 3]
my_method(1, *arguments)
كلاهما مكافئ لما يلي:
my_method(1, 2, 3)
في حالة كان التابع يستقبل وسائط مسماة، فاستخدام معامل الفصل حينها سيحوّل الجدول Hash الموجود في نهاية المصفوفة إلى وسائط مسماة:
def my_method(a, b, c: 3)
end
arguments = [1, 2, { c: 4 }]
my_method(*arguments)
يمكنك أيضًا استخدام الرمز **
(سيأتي شرحه لاحقًا) لتحوّل عناصر الجدول Hash إلى وسائط مسماة.
إذا لم يطابق عددُ الكائنات في المصفوفة عددَ المعاملات في التابع، فسيظهر الخطأ ArgumentError
.
وإذا جاء معامل الفصل في بداية الوسائط عند الاستدعاء، فيجب استخدام الأقواس عندها منعًا لظهور تحذير (warning).
التحويل من جدول Hash إلى وسائط مسماة
لنأخذ هذا التابع على سبيل المثال:
def my_method(first: 1, second: 2, third: 3)
end
يمكنك تحويل محتوى الجدول Hash إلى وسائط مسماة باستخدام المعامل **
:
arguments = { first: 3, second: 4, third: 5 }
my_method(**arguments)
أو:
arguments = { first: 3, second: 4 }
my_method(third: 5, **arguments)
كلاهما مكافئ لما يلي:
my_method(first: 3, second: 4, third: 5)
استخدم المعامل **
في تعريف التابع لتجمّع الوسائط المسماة أيًا كانت، إذ أنّها لن تُجمّع باستخدام المعامل *
:
def my_method(*a, **kw)
p arguments: a, keywords: kw
end
my_method(1, 2, '3' => 4, five: 6)
وتكون النتيجة:
{:arguments=>[1, 2, {"3"=>4}], :keywords=>{:five=>6}}
على عكس معامل الفصل الموضّح سابقًا، فإنّ المعامل **
ليس له اسم معيّن متعارف عليه.
التحويل من الكائنات Proc
إلى كتل برمجية
لنأخذ التابع التالي على سبيل المثال:
def my_method
yield self
end
يمكنك تحويل كائن من النوع proc
أو lambda
إلى كتلة برمجيّة باستخدام المعامل &
:
argument = proc { |a| puts "#{a.inspect} was yielded" }
my_method(&argument)
إذا سبق في الاستدعاء معامل الفصل *
، فيجب حينها استخدام الاقواس منعًا لظهور تحذير.
وكما هو الحال بالنّسبة للمعامل **
، فإنّ المعامل &
أيضًا ليس له اسم معيّن متعارف عليه.
البحث عن التوابع
عندما ترسل رسالة، فإنّ مفسر روبي يبحث عن التابع الذي يطابق اسم مستقبل الرسالة؛ هذه التّوابع مخزّنة في أصناف (classes) ووحدات (modules) يمرّ المفسّر عليها أثناء عمليّة البحث، ولا يبحث في كائناتها.
هذا هو الترتيب المتّبع في عمليّة البحث عن تابع للصنف أو الوحدة R الخاصّ بمستقبل معين:
- وحدات R السابقة بترتيب عكسيّ.
- تابع مطابق في R.
- الوحدات المتضمّنة في R بترتيب عكسيّ.
وإذا كان للصنفّ R صنف أب (superclass)، فستكرّر العمليّة في الصنف الأب حتى يُعثَر على التابع، وتتوقّف عمليّة البحث متى عُثر على التابع.
وإذا لم يُعثر على أيّ نتيجة، فستعاد العمليّة من البداية لكن بالبحث عن method_missing
، والتابع الافتراضيّ له BasicObject.method_missing
والذي يسبّب ظهور الخطأ NameError
عندما يستدعى.
عند تفعيل ميزة التحسينات الاختبارية، فسيتغيّر ترتيب البحث عن التوابع، اقرأ توثيق التحسينات لمزيد من التفاصيل.