الفرق بين المراجعتين لصفحة: «Ruby/calling methods»

من موسوعة حسوب
نسخ الترجمة قبل تنسيقها
 
طلا ملخص تعديل
 
(مراجعتان متوسطتان بواسطة مستخدمين اثنين آخرين غير معروضتين)
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE: استدعاء التوابع في روبي}}</noinclude>
= استدعاء التوابع في لغة روبي =
عندما تستدعي تابعًا، فإنّك تمرّر رسالة لكائن معيّن لأجل تنفيذ مهمّة معيّنة، ويتمّ ذلك في لغة روبي كالتّالي:<syntaxhighlight lang="ruby">
عندما تستدعي تابعًا، فإنّك تمرّر رسالة لكائن معيّن لأجل تنفيذ مهمّة معيّنة، ويتمّ ذلك في لغة روبي كالتّالي:
 
my_method()
my_method()
 
</syntaxhighlight>لاحظ أنّ استخدام الأقواس المنحنية هنا اختياريّ:<syntaxhighlight lang="ruby">
لاحظ أنّ استخدام الأقواس المنحنية هنا اختياريّ:
 
my_method
my_method
</syntaxhighlight>المعتمد في هذا التّوثيق أن تُستخدّم الأقواس عند وجود المعامِلات لإزالة الالتباس، إلا في حالة وجود فرق بين وجود الأقواس وحذفها.


المعتمد في هذا التّوثيق أن تُستخدّم الأقواس عند وجود المعامِلات لإزالة الالتباس، إلا في حالة وجود فرق بين وجود الأقواس وحذفها.
هذا القسم يغطّي فقط كيفيّة استدعاء التوابع، وستُشرَح كيفيّة [[Ruby/methods|تعريف التّوابع]] في قسم آخر.
 
==المستقبِل==
هذا القسم يغطّي فقط كيفيّة استدعاء التوابع، وستُشرَح كيفيّة تعريف التّوابع في قسم آخر.
المستقبِل (Receiver) الافتراضي في لغة روبي هو <code>self</code> وهو الذي يُستخدَم في حال عدم تحديد أيّ مستقبل آخر. ولأجل تحديد مستقبِل، يستَدعى التابع بالشّكل التالي:<syntaxhighlight lang="ruby">
 
== المستقبِل ==
المستقبِل الافتراضي في لغة روبي هو self وهو الذي يُستخدَم في حال عدم تحديد أيّ مستقبل آخر. ولأجل تحديد مستقبِل يستَدعى التابع بالشّكل التالي:
 
my_object.my_method
my_object.my_method
</syntaxhighlight>في هذه الحالة تُرسل رسالة <code>my_method</code> إلى الكائن <code>my_object</code>. فكلّ كائن يمكنه أن يكون مستقبِلًا لتابع ما؛ لكن حتى يتمّ ذلك، يجب أن يكون التابع مرئيًّا لهذا الكائن، وإلّا فسيظهر خطأ من نوع <code>[[Ruby/NoMethodError|NoMethodError]]</code>. 


في هذه الحالة تُرسل رسالة my_method إلى الكائن my_object. فكلّ كائن يمكنه أن يكون مستقبِلًا لتابع ما، لكن حتى يتمّ ذلك يجب أن يكون التابع مرئيّ  لهذا الكائن، وإلّا فسيظهر خطأ من نوع NoMethodError. 
يمكنك استخدام المعامل <code>.&</code> (متبوعًا بنقطة) لتعيّن <code>&</code> كمستقبل، حينها لن يُنفّذ التابع <code>my_method</code>، وستكون النتيجة <code>nil</code> عندما يكون المستقبِل <code>nil</code>، ولن تُقيَّم معامِلات التّابع <code>my_method</code> في هذه الحالة.
 
يمكنك استخدام & متبوعة بنقطة لتعيّن & كمستقبل، حينها لن يُنفّذ التابع، وستكون النتيجة nil عندما يكون المستقبِل nil، ولن تُقيَّم معامِلات التّابع.
 
كما يمكنك استخدام :: لتعيين المستقبل، لكنّ هذه الطريقة نادرة الاستخدام لأنّها قد تسبّب التباسًا مع الرمز :: المستخدم في مجالات الأسماء (namespaces).
 
== المعاملات ==
تدعم لغة روبي ثلاثة أنواع من المعامِلات التي يمكن تمريرها عند إرسال الرسائل وهي: المعاملات الموضعية، معاملات القيم المفتاحية (أو ذات الاسم)، ومعاملات الكتلة البرمجية. كل رسالة تُرسَل تستخدم نوعًا أو اثنين أو كل هذه الأنواع، إلّا أنّها إذا استُخدمت معًا فيجب أن تكون ضمن هذا الترتيب نفسه.


كلّ المعاملات في لغة روبي تُمرّر مرجعيًا ولا يؤجّل تقييمها. وكلّ معامل يُكتب متبوعًا بفاصلة , كالتّالي:
كما يمكنك استخدام <code>::</code> لتعيين المستقبل، لكنّ هذه الطريقة نادرة الاستخدام لأنّها قد تسبّب التباسًا مع الرمز <code>::</code> المستخدم في مجالات الأسماء (namespaces).
==الوسائط==
تدعم لغة روبي ثلاثة أنواع من الوسائط (arguments) التي يمكن تمريرها عند إرسال الرسائل وهي: الوسائط الموضعية، ووسائط القيم المفتاحية (أوالوسائط المسماة [named arguments])، ووسائط الكتلة البرمجية. كل رسالة تُرسَل تستخدم نوعًا أو اثنين أو كل هذه الأنواع، إلّا أنّها إذا استُخدمت معًا، فيجب أن تكون ضمن هذا الترتيب نفسه.


كلّ الوسائط في لغة روبي تُمرّر مرجعيًا ولا يؤجّل تقييمها. تفصل الوسائط بالفاصلة <code>,</code> بالشكل التالي:<syntaxhighlight lang="ruby">
my_method(1, '2', :three)
my_method(1, '2', :three)
 
</syntaxhighlight>يُمكن أن تكون الوسائط على شكل تعبير برمجي [[Ruby/Hash|كالجدول Hash]]:<syntaxhighlight lang="ruby">
يُمكن أن تكون المعاملات على شكل تعبير برمجي كالمصنِّفات (Hashes):
 
'key' => value
'key' => value
 
</syntaxhighlight>أو وسائط مسماة (Keyword arguments):<syntaxhighlight lang="ruby">
أو معاملات القيم المفتاحية (Keyword arguments):
 
key: value
key: value
 
</syntaxhighlight>[[Ruby/Hash|الجداول Hash]] والوسائط المسماة يجب أن تكون متجاورة ويجب أن تتلو الوسائط الموضعيّة، ولا بأس في أن تُخلط فيما بينها:<syntaxhighlight lang="ruby">
المصنِّفات ومعاملات القيم المفتاحية يجب أن تكون متجاورة ويجب أن تتلو المعاملات الموضعيّة، ولا بأس في أن تُخلط فيما بينها:
 
my_method('a' => 1, b: 2, 'c' => 3)
my_method('a' => 1, b: 2, 'c' => 3)
 
</syntaxhighlight>
== المعاملات الموضعيّة ==
==الوسائط الموضعيّة==
المعاملات الموضعيّة للرسالة تتبع اسم التابع مباشرة:
تتبع الوسائط الموضعيّة (Positional Arguments) للرسالة اسم التابع مباشرة:<syntaxhighlight lang="ruby">
 
my_method(argument1, argument2)
my_method(argument1, argument2)
 
</syntaxhighlight>في كثير من الحالات، لا تكون الأقواس ضروريّة عند إرسال الرسالة:<syntaxhighlight lang="ruby">
في كثير من الحالات لا تكون الأقواس ضروريّة عند إرسال الرسالة:
 
my_method argument1, argument2
my_method argument1, argument2
 
</syntaxhighlight>لكنّها ضروريّة لإزالة الالتباس، فالمثال التّالي سيسبب خطأً في صيغة (<code>[[Ruby/SyntaxError|SyntaxError]]</code>)  بسبب أنّ مفسّر لغة روبي لن يعرف إلى من يجب إرسال الوسيط الثالث <code>argument3</code>:<syntaxhighlight lang="ruby">
لكنّها ضروريّة لإزالة الالتباس، فالمثال التّالي سيسبب خطأ صيغة (SyntaxError)  بسبب أنّ مفسّر اللّغة لن يعرف إلى من يجب إرسال المعامل الثالث argument3:
 
method_one argument1, method_two argument2, argument3
method_one argument1, method_two argument2, argument3
</syntaxhighlight>إذا احتوى تعريف التابع على وسيط مبدوء برمز <code>*</code>، فالوسائط الموضعيّة الإضافيّة ستُسنَد إلى هذا الوسيط في التابع على هيئة مصفوفة.


إذا احتوى تعريف التابع على معامل مبدوء برمز *، فالمعاملات الموضعيّة الإضافيّة ستُسند إلى هذا المعامل في التابع على هيئة مصفوفة.
إذا لم يحتوِ تعريف التابع على وسائط مسماة، فإنّ أيّة وسائط مسماة أو الوسائط ذات [[Ruby/Hash|النوع Hash]] ستُسند جميعها [[Ruby/Hash|كجدول Hash]] واحد إلى آخر وسيط في تعريف التابع:<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>إذا مُرر عدد كبير من الوسائط الموضعية، فسيسبب ذلك ظهور الخطأ <code>[[Ruby/ArgumentError|ArgumentError]]</code>.
==الوسائط الموضعية الافتراضية==
عندما تعرَّف وسائط افتراضية في تعريف التابع، فلست بحاجة إلى تزويده بكل الوسائط عند الاستدعاء، فالمفسّر سيملأ المعاملات الناقصة وفق الترتيب.


إذا مُرر عدد كبير من المعاملات الموضعية فسيسبب ذلك ظهور خطأ معاملات (ArgumentError).
ففي أبسط الحالات، عندما تكون الوسائط الافتراضية هي الأخيرة في أقصى اليمين مثل:<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>لكلّ من المعاملين <code>c</code> و <code>d</code> قيمة افتراضية، فإذا مُرِّر معاملين فقط في استدعاء التابع مثل:<syntaxhighlight lang="ruby">
لكلّ من المعاملين c و d قيمة افتراضية، فإذا مرّرت معاملين فقط في استدعاء التابع:
 
my_method(1, 2)
my_method(1, 2)
 
</syntaxhighlight>فستكون النتيجة كالتالي:<syntaxhighlight lang="text">
You will see ruby print [1, 2, 3, 4].
 
فستكون النتيجة كالتالي:
 
[1, 2, 3, 4] 
[1, 2, 3, 4] 
 
</syntaxhighlight>وإذا مرّرت ثلاثة معاملات:<syntaxhighlight lang="ruby">
وإذا مرّرت ثلاثة معاملات:
 
my_method(1, 2, 5)
my_method(1, 2, 5)
 
</syntaxhighlight>فستكون النتيجة:<syntaxhighlight lang="text">
فستكون النتيجة
 
[1, 2, 5, 4]
[1, 2, 5, 4]
</syntaxhighlight>حيث يملأ مفسّر روبي المعاملات النّاقصة من اليسار إلى اليمين.


حيث يملأ مفسّر اللّغة المعاملات النّاقصة من اليسار إلى اليمين.
تسمح لغة روبي بأن توضع الوسائط الافتراضية في المنتصف بين الوسائط الموضعية الأخرى. لنأخذ هذا المثال الأكثر تعقيدًا: <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>هنا <code>b</code> و <code>c</code> يأخذان قيمًا افتراضيّة. فإذا مُرِّر معاملين فقط في استدعاء التابع بالشكل:<syntaxhighlight lang="ruby">
هنا b و c يأخذان قيمًا افتراضيّة. فإذا مرّرت معاملين فقط في استدعاء التابع:
 
my_method(1, 4)
my_method(1, 4)
 
</syntaxhighlight>ستكون النتيجة:<syntaxhighlight lang="text">
ستكون النتيجة:
 
[1, 2, 3, 4]
[1, 2, 3, 4]
 
</syntaxhighlight>وإذا مُرِّر ثلاثة معاملات:<syntaxhighlight lang="ruby">
وإذا مررت ثلاثة معاملات:
 
my_method(1, 5, 6)
my_method(1, 5, 6)
 
</syntaxhighlight>ستكون النتيجة:<syntaxhighlight lang="text">
ستكون النتيجة:
 
[1, 5, 3, 6]
[1, 5, 3, 6]
</syntaxhighlight>من الصّعب وصف الذي يحصل هنا بالكلمات، لذلك سنشرحها باستخدام المتغيّرات وقيمها.


من الصّعب وصف الذي يحصل هنا بالكلمات، لذلك سنشرحها باستخدام المتغيّرات وقيمها.
بداية تُسند القيمة 1 إلى <code>a</code>، ثمّ تسند القيمة 6 إلى <code>d</code>. وهكذا يبقى المعاملَين ذوَي القيمة الافتراضية. وطالما أنّ القيمة 5 لم تُسنَد بعد، فستعطى إلى <code>b</code>، ويحصل <code>c</code> على القيمة الافتراضية 3.
 
==الوسائط المسماة==
بداية تُسند القيمة 1 إلى ثمّ تسند القيمة 6 إلى d. وهكذا يبقى المعاملَين ذوَي القيمة الافتراضية. وطالما أنّ القيمة 5 لم تُسند بعد فستعطى إلى ويحصل c على القيمة الافتراضية 3.
الوسائط المسماة تلي الوسائط الموضعية ويفصل بينها فواصل:<syntaxhighlight lang="ruby">
 
== معاملات القيم المفتاحية ==
معاملات القيم المفتاحية تلي المعاملات الموضعية ويفصل بينها فواصل:
 
my_method(positional1, keyword1: value1, keyword2: value2)
my_method(positional1, keyword1: value1, keyword2: value2)
 
</syntaxhighlight>إذا لم تظهر الوسائط المسماة عند استدعاء التابع رغم وجودها في تعريفه، فستأخذ القيمة الافتراضيّة المعرّفة فيه. أمّا إذا مُرّرت هذه الوسائط في الاستدعاء دون أن يحتوي عليها تعريف التّابع، فسيظهر حينئذ الخطأ <code>[[Ruby/ArgumentError|ArgumentError]]</code>.
إذا لم تظهر معاملات القيم المفتاحيّة عند استدعاء التابع رغم وجودها في تعريفه فستأخذ القيمة الافتراضيّة المعرّفة فيه. أمّا إذا مُرّرت هذه المعاملات في الاستدعاء دون أن يحتوي عليها تعريف التّابع فسيظهر حينئذ خطأ معاملات (ArgumentError).
==وسائط الكتل البرمجية==
 
وسائط الكتل البرمجيّة تمرّر كتلة برمجيّة من النّطاق الذي يستدعي التّابع، ويكون ترتيب هذه الوسائط دائمًا في نهاية الوسائط الممرّرة للتابع. وتُمرّر الكتلة البرمجيّة باستخدام <code>do.. end</code> أو الأقواس <code>{..}</code>:<syntaxhighlight lang="ruby">
== معاملات الكتل البرمجية ==
معاملات الكتل البرمجيّة تمرّر كتلة برمجيّة من النّطاق الذي يستدعي التّابع، ويكون ترتيب هذه المعاملات دائمًا في نهاية المعاملات الممرّرة للتابع. وتُمرّر الكتلة البرمجيّة باستخدام do.. end أو الأقواس {..}:
 
my_method do
my_method do
 # ...
 # ...
end
end
 
</syntaxhighlight>أو:<syntaxhighlight lang="ruby">
or:
 
أو:
 
my_method {
my_method {
 # ...
 # ...
}
}
 
</syntaxhighlight>تأخذ <code>do-end</code> أولويّة أدنى من القوسين <code>{}</code> المعقوصين؛ ففي المثال التّالي:<syntaxhighlight lang="ruby">
تأخذ do-end أولويّة أدنى من {}، ففي المثال التّالي:
 
method_1 method_2 {
method_1 method_2 {
 # ...
 # ...
}
}
 
</syntaxhighlight>تُرسل الكتلة البرمجيّة إلى التابع <code>method_2</code>؛ بينما في المثال:<syntaxhighlight lang="ruby">
تُرسل الكتلة البرمجيّة إلى التابع method_2، بينما في المثال:
 
method_1 method_2 do
method_1 method_2 do
 # ...
 # ...
end
end
</syntaxhighlight>ترسل الكتلة إلى التابع <code>method_1</code>.


ترسل الكتلة إلى التابع method_1. لاحظ أنّه في حال استخدمت الأقواس {} في الحالة الأولى فسترسل الكتلة إلى التابع الأول method_1.
يمكن أن تستقبل الكتلة البرمجية وسائط من التابع المرسلة له. هذه الوسائط تعرّف بطريقة مشابهة لطريقة تعريفها في التوابع، وتمرّر ضمن <code>|...|</code> بعد كلمة <code>do</code> أو القوس المفتتح للكتلة:<syntaxhighlight lang="ruby">
 
يمكن أن تستقبل الكتلة البرمجية معاملات من التابع المرسلة له. هذه المعاملات تعرّف بطريقة مشابهة لطريقة تعريفها في التوابع، وتمرّر ضمن |...| بعد كلمة do أو القوس المفتتح للكتلة:
 
my_method do |argument1, argument2|
my_method do |argument1, argument2|
 # ...
 # ...
end
end
 
</syntaxhighlight>
== المعاملات المحليّة للكتلة البرمجيّة ==
==الوسائط المحلية للكتلة البرمجية==
يمكنك أيضًا تعريف معاملات محليّة على مستوى الكتلة البرمجيّة باستخدام الرّمز ; في قائمة معاملات الكتلة. لاحظ أنّ إسناد قيم إلى هذه المعاملات ليس له أيّ تأثير على المتغيّرات المحليّة التي لها نفس الاسم والموجودة خارج هذه الكتلة في النطاق الذي يستدعي التابع:
يمكنك أيضًا تعريف وسائط محليّة على مستوى الكتلة البرمجيّة باستخدام الرّمز <code>;</code> في قائمة وسائط الكتلة. لاحظ أنّ إسناد قيم إلى هذه الوسائط ليس له أيّ تأثير على المتغيّرات المحليّة التي لها نفس الاسم والموجودة خارج هذه الكتلة في النطاق الذي يستدعي التابع:<syntaxhighlight lang="ruby">
 
def my_method
def my_method
 yield self
 yield self
end
end
place = "world"
place = "world"
my_method do |obj; place|
my_method do |obj; place|
 place = "block"
 place = "block"
 puts "hello #{obj} this is #{place}"
 puts "hello #{obj} this is #{place}"
end
end
puts "place is: #{place}"
puts "place is: #{place}"
 
</syntaxhighlight>وتكون النتيجة:<syntaxhighlight lang="text">
وتكون النتيجة:
 
hello main this is block
hello main this is block
place is world
place is world
 
</syntaxhighlight>فالمتغيّر <code>place</code> ضمن الكتلة الممرّرة إلى التابع ليس نفسه المتغيّر <code>place</code> خارجها، وبالمقابل لو حذفنا <code>place ;</code> من وسائط الكتلة، فستكون النتيجة:<syntaxhighlight lang="text">
فالمتغيّر place ضمن الكتلة الممرّرة إلى التابع ليس نفسه المتغيّر place خارجها، وبالمقابل لو حذفنا ;place من معاملات الكتلة ستكون النتيجة:
 
hello main this is block
hello main this is block
place is block
place is block
 
</syntaxhighlight>
== التحويل من مصفوفة إلى معاملات ==
==التحويل من مصفوفة إلى وسائط==
ليكن لدينا هذا التابع:
ليكن لدينا هذا التابع:<syntaxhighlight lang="ruby">
 
def my_method(argument1, argument2, argument3)
def my_method(argument1, argument2, argument3)
end
end
 
</syntaxhighlight>يمكنك تحويل مصفوفة إلى سلسلة من الوسائط عن طريق تمرير المصفوفة مسبوقة برمز النجمة <code>*</code> (المسمى بمعامل الفصل):<syntaxhighlight lang="ruby">
يمكنك تحويل مصفوفة إلى سلسلة من المعاملات عن طريق تمرير المصفوفة مسبوقة برمز النجمة * أو المسمى بمعامل الفصل:
 
arguments = [1, 2, 3]
arguments = [1, 2, 3]
my_method(*arguments)
my_method(*arguments)
 
</syntaxhighlight>أو:<syntaxhighlight lang="ruby">
أو:
 
arguments = [2, 3]
arguments = [2, 3]
my_method(1, *arguments)
my_method(1, *arguments)
 
</syntaxhighlight>كلاهما مكافئ لما يلي:<syntaxhighlight lang="ruby">
كلاهما مكافئ لما يلي:
 
my_method(1, 2, 3)
my_method(1, 2, 3)
 
</syntaxhighlight>في حالة كان التابع يستقبل وسائط مسماة، فاستخدام معامل الفصل حينها سيحوّل [[Ruby/Hash|الجدول Hash]] الموجود في نهاية المصفوفة إلى وسائط مسماة:<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>يمكنك أيضًا استخدام الرمز <code>**</code> (سيأتي شرحه لاحقًا) لتحوّل عناصر [[Ruby/Hash|الجدول Hash]] إلى وسائط مسماة.


يمكنك أيضًا استخدام الرمز ** (سيأتي شرحه لاحقًا) لتحوّل مصنّفًا إلى معامل قيم مفتاحية.
إذا لم يطابق عددُ الكائنات في المصفوفة عددَ المعاملات في التابع، فسيظهر الخطأ <code>[[Ruby/ArgumentError|ArgumentError]]</code>.
 
إذا لم يطابق عددُ الكائنات في المصفوفة عددَ المعاملات في التابع فسيظهر خطأ معاملات (ArgumentError).
 
وإذا جاء معامل الفصل في بداية المعاملات عند الاستدعاء، فيجب استخدام الأقواس عندها منعًا لظهور تحذير (warning).
 
== التحويل من تصنيف إلى معامل قيم مفتاحية ==
لنأخذ هذا التابع على سبيل المثال:


وإذا جاء معامل الفصل في بداية الوسائط عند الاستدعاء، فيجب استخدام الأقواس عندها منعًا لظهور تحذير (warning).
==التحويل من جدول Hash إلى وسائط مسماة==
لنأخذ هذا التابع على سبيل المثال:<syntaxhighlight lang="ruby">
def my_method(first: 1, second: 2, third: 3)
def my_method(first: 1, second: 2, third: 3)
end
end
 
</syntaxhighlight>يمكنك تحويل محتوى [[Ruby/Hash|الجدول Hash]] إلى وسائط مسماة باستخدام المعامل <code>**</code>:<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 lang="ruby">
أو:
 
arguments = { first: 3, second: 4 }
arguments = { first: 3, second: 4 }
my_method(third: 5, **arguments)
my_method(third: 5, **arguments)
 
</syntaxhighlight>كلاهما مكافئ لما يلي:<syntaxhighlight lang="ruby">
كلاهما مكافئ لما يلي:
 
my_method(first: 3, second: 4, third: 5)
my_method(first: 3, second: 4, third: 5)
 
</syntaxhighlight>استخدم المعامل <code>**</code> في تعريف التابع لتجمّع الوسائط المسماة أيًا كانت، إذ أنّها لن تُجمّع باستخدام المعامل <code>*</code>:<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 lang="text">
وتكون النتيجة:
{:arguments=>[1, 2, {"3"=>4}], :keywords=>{:five=>6}}
 
</syntaxhighlight>على عكس معامل الفصل الموضّح سابقًا، فإنّ المعامل <code>**</code> ليس له اسم معيّن متعارف عليه.
<nowiki>{:arguments=>[1, 2, {"3"=>4}], :keywords=>{:five=>6}}</nowiki>
==التحويل من الكائنات <code>Proc</code> إلى كتل برمجية==
 
لنأخذ التابع التالي على سبيل المثال:<syntaxhighlight lang="ruby">
على عكس معامل الفصل الموضّح سابقًا فإنّ المعامل ** ليس له اسم معيّن متعارف عليه.
 
== التحويل من كائنات Proc إلى كتل برمجيّة ==
لنأخذ التابع التالي على سبيل المثال:
 
def my_method
def my_method
 yield self
 yield self
end
end
 
</syntaxhighlight>يمكنك تحويل كائن من النوع <code>[[Ruby/Proc|proc]]</code> أو <code>lambda</code> إلى كتلة برمجيّة باستخدام المعامل <code>&</code>:<syntaxhighlight lang="ruby">
يمكنك تحويل كائن من نوع proc أو lambda إلى كتلة برمجيّة باستخدام المعامل &:
 
argument = proc { |a| puts "#{a.inspect} was yielded" }
argument = proc { |a| puts "#{a.inspect} was yielded" }
my_method(&argument)
my_method(&argument)
</syntaxhighlight>إذا سبق في الاستدعاء معامل الفصل <code>*</code>، فيجب حينها استخدام الاقواس منعًا لظهور تحذير.


إذا سبق في الاستدعاء معامل الفصل * فيجب حينها استخدام الاقواس منعًا لظهور تحذير.
وكما هو الحال بالنّسبة للمعامل <code>**</code>،  فإنّ المعامل <code>&</code> أيضًا ليس له اسم معيّن متعارف عليه.
 
==البحث عن التوابع==
وكما هو الحال بالنّسبة للمعامل ** فإنّ المعامل & أيضًا ليس له اسم معيّن متعارف عليه.
عندما ترسل رسالة، فإنّ مفسر روبي يبحث عن التابع الذي يطابق اسم مستقبل الرسالة؛ هذه التّوابع مخزّنة في [[:تصنيف:Ruby Class|أصناف]] (classes) و<nowiki/>[[:تصنيف:Ruby Module|وحدات]] (modules) يمرّ المفسّر عليها أثناء عمليّة البحث، ولا يبحث في كائناتها.
 
== البحث عن التوابع ==
عندما ترسل رسالة فإنّ مفسر اللغة يبحث عن التابع الذي يطابق اسم مستقبل الرسالة، هذه التّوابع محزّنة في أصناف (classes) ووحدات (modules) يمرّ المفسّر عليها أثناء عمليّة البحث، ولا يبحث في كائناتها.
 
هذا هو الترتيب المتّبع في عمليّة البحث عن التابع للصنف أو الوحدة  R الخاصّ بالمستقبل:
* وحدات R السابقة بترتيب عكسيّ.
* تابع مطابق في R
* الوحدات المتضمّنة في R بترتيب عكسيّ
وإذا كان للصنفّ R صنف أب (superclass) فستكرّر العمليّة في الصنف الأب حتى يُعثر على التابع، وتتوقّف عمليّة البحث متى عُثر على التابع.


وإذا لم يُعثر على أيّ نتيجة فستعاد العمليّة من البداية لكن بالبحث عن method_missing، والتابع الافتراضيّ له BasicObject#method_missing والذي يسبّب ظهور خطأ اسم (NameError) عندما يستدعى.
هذا هو الترتيب المتّبع في عمليّة البحث عن تابع للصنف أو الوحدة  R الخاصّ بمستقبل معين:
*وحدات R السابقة بترتيب عكسيّ.
*تابع مطابق في R.
*الوحدات المتضمّنة في R بترتيب عكسيّ.
وإذا كان للصنفّ R صنف أب (superclass)، فستكرّر العمليّة في الصنف الأب حتى يُعثَر على التابع، وتتوقّف عمليّة البحث متى عُثر على التابع.


عند تفعيل ميزة التحسينات الاختبارية فسيتغيّر ترتيب البحث عن التوابع، اقرأ توثيق التحسينات لمزيد من التفاصيل.
وإذا لم يُعثر على أيّ نتيجة، فستعاد العمليّة من البداية لكن بالبحث عن <code>method_missing</code>، والتابع الافتراضيّ له <code>BasicObject.method_missing</code> والذي يسبّب ظهور الخطأ  <code>[[Ruby/NameError|NameError]]</code> عندما يستدعى.


== مصادر ==
عند تفعيل ميزة [[Ruby/refinements|التحسينات]] الاختبارية، فسيتغيّر ترتيب البحث عن التوابع، اقرأ توثيق [[Ruby/refinements|التحسينات]] لمزيد من التفاصيل.
* [https://ruby-doc.org/core-2.5.1/doc/syntax/calling_methods_rdoc.html صفحة Calling Methods في توثيق روبي الرسمي.]
==مصادر==
*[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 عندما يستدعى.

عند تفعيل ميزة التحسينات الاختبارية، فسيتغيّر ترتيب البحث عن التوابع، اقرأ توثيق التحسينات لمزيد من التفاصيل.

مصادر