الفرق بين المراجعتين لصفحة: «Ruby/methods»
أنشأ الصفحة ب'= التوابع: = التوابع في لغة روبي تتضمّن الوظائف التي يقوم بها برنامجك. إليك هذا المثال لتعريف ت...' |
جميل-بيلوني (نقاش | مساهمات) ط مراجعة وتدقيق. |
||
(4 مراجعات متوسطة بواسطة مستخدم واحد آخر غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE: التوابع في روبي}}</noinclude> | |||
التوابع في لغة روبي | تتضمّن التوابع في لغة روبي الوظائف التي يقوم بها برنامجك. إليك هذا المثال لتعريف تابع بسيط:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def one_plus_one | def one_plus_one | ||
1 + 1 | 1 + 1 | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>تعريف التابع يتكوّن من الكلمة المحجوزة <code>def</code> يتبعها اسم التابع، ثمّ جسم التابع، فالقيمة المعادة وفي النهاية الكلمة المحجوزة <code>end</code>. فعند تنفيذ التابع في المثال السابق، ستُعاد القيمة 2. هذا القسم سيغطّي تعريف التّوابع. ارجع إلى توثيق [[Ruby/calling methods|استدعاء التوابع]] لتتعرف على الصيغ المستخدمة لذلك الغرض. | ||
تعريف التابع يتكوّن من الكلمة المحجوزة def يتبعها اسم التابع، ثمّ جسم التابع، فالقيمة المعادة وفي النهاية الكلمة المحجوزة end. فعند تنفيذ التابع في المثال | ==تسمية التوابع== | ||
هذا القسم سيغطّي تعريف التّوابع. ارجع إلى | يمكن أن تستخدم لاسم التابع أحد المعاملات، وإلا فعليك أن تبتدئه بحرف أبجديّ أو أيّ محرف من محارف لوحة المفاتيح (أيضًا تعرف باسم محارف البتات الثمانية أي كل محرف بحجم 8 بت). ويمكن للاسم أن يتضمن أحرفًا وأرقامًا وشرطة سفليّة (_)، أو أيّ محرف من محارف البتات الثمانية. ومن المعتاد أن تستخدم الشرطة السفليّة لتفصل بين الكلمات في أسماء التوابع التي تتضمن كلمات عدّة.<syntaxhighlight lang="ruby"> | ||
== تسمية التوابع == | |||
يمكن أن تستخدم لاسم التابع أحد المعاملات، وإلا فعليك أن تبتدئه بحرف أبجديّ أو أيّ محرف من محارف لوحة المفاتيح (أيضًا تعرف باسم محارف البتات الثمانية). ويمكن للاسم أن يتضمن أحرفًا وأرقامًا وشرطة سفليّة | |||
<syntaxhighlight lang="ruby"> | |||
def method_name | def method_name | ||
puts "use underscores to separate words" | puts "use underscores to separate words" | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>يجب أن تكتب البرامج بلغة روبي باستخدام مجموعات محارف متوافقة مع مجموعة المحارف [[Arduino/asciichart|US-ASCII]] مثل UTF-8 و ISO-8859-1. فإذا كان البتات الثمانية مضبوطة في مجموعات المحارف هذه، فهذا يدل على أنّ المحرف هو من المحارف الموسّعة، ولغة روبي تسمح أن تحتوي أسماء التوابع والمعرّفات الأخرى على تلك المحارف. إلا أنّ لغة روبي لا تسمح باستخدام بعض المحارف مثل [[Arduino/asciichart|ASCII NUL]] الذي رمزه \x00. | ||
يجب أن تكتب البرامج بلغة روبي باستخدام مجموعات محارف متوافقة مع مجموعة المحارف US-ASCII مثل UTF-8 و ISO-8859-1. فإذا كان البتات الثمانية مضبوطة في مجموعات المحارف هذه، فهذا يدل على أنّ المحرف هو من المحارف الموسّعة، ولغة روبي تسمح أن تحتوي أسماء التوابع والمعرّفات الأخرى على تلك المحارف. إلا أنّ لغة روبي لا تسمح باستخدام بعض المحارف مثل ASCII NUL الذي رمزه \x00. | |||
إليك بعض الأمثلة عن التوابع التي تصلح تسميتها في لغة روبي: | إليك بعض الأمثلة عن التوابع التي تصلح تسميتها في لغة روبي:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def hello | def hello | ||
"hello" | "hello" | ||
سطر 24: | سطر 19: | ||
puts "means hello in Japanese" | puts "means hello in Japanese" | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>وعادة ما تكون أسماء التوابع متوافقة مع نظام [[Arduino/asciichart|US-ASCII]] كون الحروف الخاصة به متوفرة على جميع لوحات المفاتيح. ويمكن لأسماء التوابع أن تنتهي بعلامة التعجّب <code>!</code> أو علامة الاستفهام <code>?</code> أو علامة المساواة <code>=</code>. | ||
وعادة ما تكون أسماء التوابع متوافقة مع نظام US-ASCII كون الحروف الخاصة به متوفرة على جميع لوحات المفاتيح. | |||
ويمكن لأسماء التوابع أن تنتهي بعلامة التعجّب ! أو علامة الاستفهام ? أو علامة المساواة = . | إن التوابع المنتهية بعلامة تعجب تستدعى وتُنفّذ مثل أيّ تابع آخر، إلّا أنّها عادة ما تصنّف كتوابع خطرة. ففي مكتبة نواة لغة روبي يُعدّ التّابع خطيرًا إذا كان يغيّر من قيمة المتغيّر الذي يستقبله، ولذلك يُميّز بعلامة التعجّب في آخره. | ||
إن التوابع المنتهية بعلامة تعجب تستدعى وتُنفّذ مثل أيّ تابع آخر، إلّا أنّها عادة ما تصنّف كتوابع خطرة. ففي مكتبة نواة لغة روبي يُعدّ التّابع خطيرًا إذا كان يغيّر من قيمة المتغيّر الذي يستقبله، ولذلك يُميّز بعلامة التعجّب في آخره. وفي هذه المكتبة يوجد لكلّ تابع من هذا النّوع تابعًا آخر مقابلًا ليس خطيرًا أي أنّه لا يغيّر من قيمة المتغيّر الذي يستقبله، وهذه التّوابع يكون لها نفس التسمية إلا أنّها لا تنتهي بإشارة التّعجب. | |||
أمّا المتعارف عليه بالنّسبة للتوابع التي تنتهي تسميتها بإشارة استفهام فهي التوابع التي تُرجع قيمة منطقيّة، لكنّها | وفي هذه المكتبة يوجد لكلّ تابع من هذا النّوع تابعًا آخر مقابلًا ليس خطيرًا أي أنّه لا يغيّر من قيمة المتغيّر الذي يستقبله، وهذه التّوابع يكون لها نفس التسمية إلا أنّها لا تنتهي بإشارة التّعجب. | ||
والتوابع التي تنتهي بإشارة مساواة فهي توابع | |||
أمّا المتعارف عليه بالنّسبة للتوابع التي تنتهي تسميتها بإشارة استفهام فهي التوابع التي تُرجع قيمة منطقيّة، لكنّها لا تعيد بالضّرورة القيمة <code>true</code> أو <code>false</code>، بل غالبًا ما تعيد كائنًا يعبّر عن <code>true</code> أو قيمة الإيجاب. | |||
والتوابع التي تنتهي بإشارة مساواة فهي توابع الإسناد؛ وبالنسبة لهذا النوع من التوابع، تُتجاهل القيمة المعادة وتُرجع معاملات التابع بدلًا منها. | |||
فيما يلي أسماء التوابع المعبرة عن مختلف العمليات في لغة روبي، كلّ واحدة من هذه العمليات تقبل معاملًا واحدًا فقط. تجد بعد رمز العملية الاستخدام الشهير لها أو اسم العملية. لاحظ أنّك إن غيّرت ما تقوم به كلّ عمليّة فستسبّب لبسًا لدى المستخدم، إذ أنّ المتوقّع من إشارة الجمع أن تجمع، ومن إشارة الطرح أن تطرح، وهكذا. أضف إلى ذلك أنّك لن تتمكّن من تغيير أولويّة أيّ من هذه العمليات. | فيما يلي أسماء التوابع المعبرة عن مختلف العمليات في لغة روبي، كلّ واحدة من هذه العمليات تقبل معاملًا واحدًا فقط. تجد بعد رمز العملية الاستخدام الشهير لها أو اسم العملية. لاحظ أنّك إن غيّرت ما تقوم به كلّ عمليّة فستسبّب لبسًا لدى المستخدم، إذ أنّ المتوقّع من إشارة الجمع أن تجمع، ومن إشارة الطرح أن تطرح، وهكذا. أضف إلى ذلك أنّك لن تتمكّن من تغيير أولويّة أيّ من هذه العمليات. | ||
{| class="wikitable" | |||
!المعامل | |||
!العملية | |||
- | |- | ||
|<nowiki>+</nowiki> | |||
<nowiki> | |جمع | ||
|- | |||
<nowiki> | |<nowiki>-</nowiki> | ||
قوة | |طرح | ||
/ | |- | ||
قسمة | |* | ||
% | |ضرب | ||
باقي القسمة، أو سلسلة % | |- | ||
& | |** | ||
AND | |قوة | ||
^ | |- | ||
|/ | |||
>> | |قسمة | ||
إزاحة لليمين | |- | ||
<< | |% | ||
إزاحة لليسار، أو إضافة | |باقي القسمة، أو سلسلة % | ||
== | |- | ||
اختبار المساواة | |& | ||
! | |العملية AND | ||
اختبار عدم المساواة | |- | ||
=== | |^ | ||
المساواة التامة | |العملية XOR | ||
= | |- | ||
مطابقة النمط (ليس خاصًّا بالتعبيرات النظامية فحسب) | |>> | ||
! | |إزاحة لليمين | ||
عدم مطابقة النمط | |- | ||
<=> | |<< | ||
المقارنة والمعروف أيضًا بمعامل سفينة الفضاء | |إزاحة لليسار، أو إضافة | ||
|- | |||
أصغر من | |== | ||
|اختبار المساواة | |||
أصغر من أو يساوي | |- | ||
|=! | |||
أكبر من | |اختبار عدم المساواة | ||
|- | |||
أكبر من أو يساوي | |=== | ||
|المساواة التامة | |||
لأجل تعريف توابع أحادية تغيّر سلوك إشارة الجمع والطرح والضرب والنفي المنطقي، عليك أن تُتبع رمز العملية بالرمز @ مثل: +@ أو !@ كما في المثال التالي: | |- | ||
<syntaxhighlight lang="ruby"> | |~= | ||
|مطابقة النمط (ليس خاصًّا بالتعبيرات النظامية فحسب) | |||
|- | |||
|~! | |||
|عدم مطابقة النمط | |||
|- | |||
|<=> | |||
|المقارنة والمعروف أيضًا بمعامل سفينة الفضاء | |||
|- | |||
|> | |||
|أصغر من | |||
|- | |||
|=> | |||
|أصغر من أو يساوي | |||
|- | |||
|< | |||
|أكبر من | |||
|- | |||
|=< | |||
|أكبر من أو يساوي | |||
|} | |||
لأجل تعريف توابع أحادية تغيّر سلوك إشارة الجمع والطرح والضرب والنفي المنطقي، عليك أن تُتبع رمز العملية بالرمز <code>@</code> مثل: <code>+@</code> أو <code>!@</code> كما في المثال التالي:<syntaxhighlight lang="ruby"> | |||
class C | class C | ||
def -@ | def -@ | ||
سطر 81: | سطر 101: | ||
end | end | ||
obj = C.new | obj = C.new | ||
-obj # | -obj # "you inverted this object" يطبع | ||
</syntaxhighlight> | </syntaxhighlight>التوابع الأحادية لا تقبل أي معاملات. بالإضافة لذلك يمكن تعريف التوابع التي تستخدم للإشارة إلى العناصر وإسناد قيمٍ إليها بالشّكل <code>[]</code> أو <code>[]=</code> على التوالي وبالترتيب. وكلاهما بالإمكان أن يأخذ معاملًا واحدًا أو أكثر. ويمكن لتابع الإشارة للعناصر ألا يأخذ أيّ معامل. <syntaxhighlight lang="ruby"> | ||
التوابع الأحادية لا تقبل أي معاملات. | |||
بالإضافة لذلك يمكن تعريف التوابع التي تستخدم للإشارة إلى العناصر وإسناد قيمٍ إليها بالشّكل [] أو []= على التوالي وبالترتيب. وكلاهما بالإمكان أن يأخذ معاملًا واحدًا أو أكثر. ويمكن لتابع الإشارة للعناصر ألا يأخذ أيّ معامل. | |||
<syntaxhighlight lang="ruby"> | |||
class C | class C | ||
def [](a, b) | def [](a, b) | ||
سطر 95: | سطر 112: | ||
end | end | ||
obj = C.new | obj = C.new | ||
obj[2, 3] # | obj[2, 3] # "5" يطبع | ||
obj[2, 3] = 4 # | obj[2, 3] = 4 # "10" يطبع | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== القيم المعادة == | ==القيم المعادة== | ||
تُعيد التوابع بشكل افتراضيّ آخر تعبير برمجيّ يصل إليه التنفيذ في جسم | تُعيد التوابع بشكل افتراضيّ آخر تعبير برمجيّ يصل إليه التنفيذ في جسم التابع؛ في المثال أعلاه، التعبير الأخير (والوحيد) الذي نُفّذ كان عمليّة جمع بسيطة 1+1. ويمكن أيضًا استخدام الكلمة المحجوزة <code>return</code> للتأكيد بأنّ يعيد التابع القيمة التي تليها.<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def one_plus_one | def one_plus_one | ||
return 1 + 1 | return 1 + 1 | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>كما يمكن استخدام كلمة <code>return</code> لإنهاء تنفيذ التابع دون إكمال التعبيرات البرمجيّة التي تليها.<syntaxhighlight lang="ruby"> | ||
كما يمكن استخدام كلمة return لإنهاء تنفيذ التابع دون إكمال التعبيرات البرمجيّة التي تليها. | |||
<syntaxhighlight lang="ruby"> | |||
def two_plus_two | def two_plus_two | ||
return 2 + 2 | return 2 + 2 | ||
1 + 1 # لا يتمّ تنفيذ هذا السطر أبدًا | 1 + 1 # لا يتمّ تنفيذ هذا السطر أبدًا | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>لاحظ أنّه - كما أشرنا سابقًا - في حالة توابع الإسناد، فإنّ القيمة المعادة تُتجاهل ويعيد التابع بدلًا منها المعامل الذي مُرّر إليه:<syntaxhighlight lang="ruby"> | ||
لاحظ أنّه - كما أشرنا سابقًا - في حالة توابع | |||
<syntaxhighlight lang="ruby"> | |||
def a=(value) | def a=(value) | ||
return 1 + value | return 1 + value | ||
end | end | ||
p(self.a = 5) # تطبع5 | p(self.a = 5) # تطبع5 | ||
</syntaxhighlight> | </syntaxhighlight>أمّا القيمة المعادة فترجع فقط في حالة استدعاء التابع بشكل مباشر:<syntaxhighlight lang="ruby"> | ||
أمّا القيمة المعادة فترجع فقط في حالة استدعاء التابع بشكل مباشر: | |||
<syntaxhighlight lang="ruby"> | |||
p send(:a=, 5) # تطبع 6 | p send(:a=, 5) # تطبع 6 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== النطاق == | ==النطاق== | ||
الصيغة النظامية لتعريف تابع: | الصيغة النظامية لتعريف تابع:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method | def my_method | ||
# ... | # ... | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>وبهذه الطريقة تضيف تابعًا إلى صنف (class). كما يمكنك تعريف تابع لأغراض صنف معين وذلك بإضافة كلمة class:<syntaxhighlight lang="ruby"> | ||
وبهذه الطريقة تضيف تابعًا إلى صنف class. كما يمكنك تعريف تابع لأغراض صنف معين وذلك بإضافة كلمة class: | |||
<syntaxhighlight lang="ruby"> | |||
class C | class C | ||
def my_method | def my_method | ||
سطر 139: | سطر 144: | ||
end | end | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>كما يمكن تعريف تابع لكائن آخر. وتستطيع تعريف تابع للصنف نفسه (وليس للكائنات المتفرعة عنه) كالتالي:<syntaxhighlight lang="ruby"> | ||
كما يمكن تعريف تابع لكائن آخر. وتستطيع تعريف تابع للصنف نفسه (وليس للكائنات المتفرعة عنه) كالتالي: | |||
<syntaxhighlight lang="ruby"> | |||
class C | class C | ||
def self.my_method | def self.my_method | ||
سطر 147: | سطر 150: | ||
end | end | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>وهذه الطريقة تُعد حالة خاصة من إحدى قواعد الصيغة في لغة روبي، وهي القدرة على إضافة تابع لأيّ كائن. وبما أنّ الأصناف بحدّ ذاتها هي نوع من الكائنات، فبالإمكان ببساطة إضافة تابع إلى كائن الصنف | ||
وهذه الطريقة تُعد حالة خاصة من إحدى قواعد الصيغة في لغة روبي، وهي القدرة على إضافة تابع لأيّ | |||
وفيما يلي صيغة إضافة تابع إلى كائن ما: | وفيما يلي صيغة إضافة تابع إلى كائن ما:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
greeting = "Hello" | greeting = "Hello" | ||
def greeting.broaden | def greeting.broaden | ||
سطر 156: | سطر 158: | ||
end | end | ||
greeting.broaden # تعيد "Hello, world!" | greeting.broaden # تعيد "Hello, world!" | ||
</syntaxhighlight> | </syntaxhighlight>كلمة <code>self</code> هي كلمة محجوزة في اللغة تشير إلى الغرض الحالي من وجهة نظر مفسّر اللغة، فهي تسهّل تعريف تابع الصنف في المثال السابق.<syntaxhighlight lang="ruby"> | ||
كلمة self هي كلمة محجوزة في اللغة تشير إلى الغرض الحالي من وجهة نظر مفسّر اللغة، فهي تسهّل تعريف تابع الصنف في المثال السابق. | |||
<syntaxhighlight lang="ruby"> | |||
def String.hello | def String.hello | ||
"Hello, world!" | "Hello, world!" | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>تعريف التابع بهذا الشكل يسمى "التابع المنفرد" (singleton method). فالتابع <code>broaden</code> في المثال السابق موجود في الكائن <code>greeting</code> فحسب، ولن تجده في أيّ متغيّر آخر من نوع السلسلة النصية <code>string</code>. | ||
تعريف التابع بهذا الشكل يسمى "التابع المنفرد singleton method | ==إعادة التعريف== | ||
== إعادة التعريف == | عندما يصادف مفسّر لغة روبي كلمة <code>def</code> قبل اسم تابع معرّف مسبقًا فإنّه لا يعدّ ذلك خطأ وإنّما يعيد تعريف هذا التابع. وهذا ما يسمّى بإعادة التعريف (Overriding). إلّا أنّ هذه الإمكانيّة في لغة روبي تُعدّ خطرة ولا يستحسن استخدامها بشكل متكّرر، إلا في حالة توسيع أصناف اللغة الأساسية (core classes)، لأنّها قد تؤدي إلى نتائج غير معروفة. خذ على سبيل المثال تسلسل الأوامر التالي:<syntaxhighlight lang="text"> | ||
عندما يصادف مفسّر لغة روبي كلمة def قبل اسم تابع معرّف مسبقًا فإنّه لا يعدّ ذلك خطأ وإنّما يعيد تعريف هذا التابع. وهذا ما يسمّى بإعادة التعريف | |||
<syntaxhighlight lang="text"> | |||
>> "43".to_i | >> "43".to_i | ||
=> 43 | => 43 | ||
سطر 177: | سطر 175: | ||
>> "43".to_i | >> "43".to_i | ||
=> 42 | => 42 | ||
</syntaxhighlight> | </syntaxhighlight>هذا سيسبب بكلّ تأكيد تخريبًا لأيّ شيفرة تستخدم التابع <code>to_i</code> من الصنف <code>String</code> لاستخلاص أعدادٍ من سلسلة نصية. | ||
هذا سيسبب بكلّ تأكيد تخريبًا لأيّ شيفرة تستخدم التابع to_i من الصنف String | ==وسائط التوابع== | ||
== | يمكن للتابع أن يقبل وسائط وتكون مكتوبة على التتالي بعد اسم التابع:<syntaxhighlight lang="ruby"> | ||
يمكن للتابع أن يقبل | |||
<syntaxhighlight lang="ruby"> | |||
def add_one(value) | def add_one(value) | ||
value + 1 | value + 1 | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>عند استدعاء التابع <code>add_one</code>، يجب على المستخدم أن يمرّر له وسيطًا، وهذا الوسيط هو متغيّر محليّ ضمن جسم التابع. ففي المثال السابق، يضيف التابع واحدًا إلى هذا الوسيط الذي مُرّر إليه، ويُعيد الناتج. فإذا أُعطي التابع 1 سيعيد 2. | ||
عند استدعاء التابع add_one يجب على المستخدم أن يمرّر له | |||
والأقواس المحيطة | والأقواس المحيطة بالوسائط اختيارية ويمكن حذفها:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def add_one value | def add_one value | ||
value + 1 | value + 1 | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>وإذا كان لديك أكثر من وسيط، فافصل بينها بفواصل:<syntaxhighlight lang="ruby"> | ||
وإذا كان لديك أكثر من | |||
<syntaxhighlight lang="ruby"> | |||
def add_values(a, b) | def add_values(a, b) | ||
a + b | a + b | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>فعند الاستدعاء، يجب تمرير الوسائط بنفس الترتيب؛ بعيارة أخرى، يمكن القول أنّ الوسائط حساسة للترتيب. | ||
فعند | ==القيم الافتراضية== | ||
== القيم الافتراضية == | يمكن أن تحصل الوسائط على قيم افتراضية:<syntaxhighlight lang="ruby"> | ||
يمكن أن تحصل | |||
<syntaxhighlight lang="ruby"> | |||
def add_values(a, b = 1) | def add_values(a, b = 1) | ||
a + b | a + b | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>ولا يشترط أن تكون القيمة الافتراضية في بداية أو نهاية الوسائط، إلّا أن الوسائط ذات القيم الافتراضية يجب أن تجمّع معًا، فالمثال التالي مقبول:<syntaxhighlight lang="ruby"> | ||
ولا يشترط أن تكون القيمة الافتراضية في بداية أو نهاية | |||
<syntaxhighlight lang="ruby"> | |||
def add_values(a = 1, b = 2, c) | def add_values(a = 1, b = 2, c) | ||
a + b + c | a + b + c | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>أما هذا المثال، فسيعطي الخطأ <code>[[Ruby/SyntaxError|SyntaxError]]</code>:<syntaxhighlight lang="ruby"> | ||
أما هذا | |||
<syntaxhighlight lang="ruby"> | |||
def add_values(a = 1, b, c = 1) | def add_values(a = 1, b, c = 1) | ||
a + b + c | a + b + c | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
تفكيك المصفوفة | ==تفكيك المصفوفة== | ||
يمكنك تفكيك مصفوفة (أوس استخراج القيم منها) باستخدام أقواس مضاعفة في معاملات التابع: | يمكنك تفكيك مصفوفة (أوس استخراج القيم منها) باستخدام أقواس مضاعفة في معاملات التابع:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method((a, b)) | def my_method((a, b)) | ||
p a: a, b: b | p a: a, b: b | ||
end | end | ||
my_method([1, 2]) | my_method([1, 2]) | ||
</syntaxhighlight> | </syntaxhighlight>هذا المثال يطبع:<syntaxhighlight lang="text"> | ||
هذا المثال يطبع: | |||
<syntaxhighlight lang="text"> | |||
{:a=>1, :b=>2} | {:a=>1, :b=>2} | ||
</syntaxhighlight> | </syntaxhighlight>ويُتجاهل كلّ عنصر في المصفوفة زائد على عدد الوسائط.<syntaxhighlight lang="ruby"> | ||
ويُتجاهل كلّ عنصر في المصفوفة زائد على عدد | |||
<syntaxhighlight lang="ruby"> | |||
def my_method((a, b)) | def my_method((a, b)) | ||
p a: a, b: b | p a: a, b: b | ||
end | end | ||
my_method([1, 2, 3]) | my_method([1, 2, 3]) | ||
</syntaxhighlight> | </syntaxhighlight>وهذا المثال له نفس نتيجة المثال السابق. | ||
وهذا المثال له نفس نتيجة المثال السابق. | |||
يمكنك استخدام الرمز * لتحصيل | يمكنك استخدام الرمز <code>*</code> لتحصيل الوسائط المتبقية أيًا كان عددها في المصفوفة؛ فالمثال التالي يفصل المصفوفة ليسند أول عنصر منها في الوسيط الأول، والباقي يسنده كمصفوفة إلى الوسيط الثاني:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method((a, *b)) | def my_method((a, *b)) | ||
p a: a, b: b | p a: a, b: b | ||
end | end | ||
my_method([1, 2, 3]) | my_method([1, 2, 3]) | ||
</syntaxhighlight> | </syntaxhighlight>هذا المثال يطبع:<syntaxhighlight lang="text"> | ||
هذا المثال يطبع: | {:a=>1, :b=>[2, 3]} | ||
<syntaxhighlight lang="text"> | </syntaxhighlight>أيّ وسيط يستجيب للتابع <code>to_ary</code> يمكن استخدامه في عملية التفكيك هذه. فإذا كان لديك كائن آخر تريد أن تفكّكه بنفس الطريقة، فعليك أن تعرّف له التابع <code>to_ary</code> الخاص به. | ||
</syntaxhighlight> | يمكنك استخدام أقواس ضمنية لتفكيك مصفوفة مُرّرت كوسيط، لكن إذا لم يكن الوسيط المقابل له من نوع [[Ruby/Array|مصفوفة]]، فسوف يُسند هذا الوسيط إلى الوسيط الأول ضمن قوسي التفكيك، بينما تأخذ بقية الوسائط القيمة <code>nil</code>:<syntaxhighlight lang="ruby"> | ||
أيّ | |||
يمكنك استخدام أقواس ضمنية لتفكيك مصفوفة مُرّرت | |||
<syntaxhighlight lang=" | |||
def my_method(a, (b, c), d) | def my_method(a, (b, c), d) | ||
p a: a, b: b, c: c, d: d | p a: a, b: b, c: c, d: d | ||
end | end | ||
my_method(1, 2, 3) | my_method(1, 2, 3) | ||
</syntaxhighlight> | </syntaxhighlight>هذا المثال يطبع:<syntaxhighlight lang="text"> | ||
هذا المثال يطبع: | |||
<syntaxhighlight lang="text"> | |||
{:a=>1, :b=>2, :c=>nil, :d=>3} | {:a=>1, :b=>2, :c=>nil, :d=>3} | ||
</syntaxhighlight> | </syntaxhighlight>كما بإمكانك تضمين عمليات التفكيك داخل بعضها بأي شكل:<syntaxhighlight lang="ruby"> | ||
كما بإمكانك تضمين عمليات التفكيك داخل بعضها بأي شكل: | |||
<syntaxhighlight lang="ruby"> | |||
def my_method(((a, b), c)) | def my_method(((a, b), c)) | ||
# ... | # ... | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== | ==الوسائط التي من النوع: مصفوفة وجدول Hash== | ||
إضافة الرمز * في بداية اسم | إضافة الرمز <code>*</code> في بداية اسم الوسيط يسبب تحويل جميع الوسائط الإضافية إلى مصفوفة:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def gather_arguments(*arguments) | def gather_arguments(*arguments) | ||
p arguments | p arguments | ||
end | end | ||
gather_arguments 1, 2, 3 # | gather_arguments 1, 2, 3 # [1, 2, 3] تطبع | ||
</syntaxhighlight> | </syntaxhighlight>ويجب أن يأتي هذا الوسيط في آخر الوسائط الموضعية وعليه أن يسبق أيّ وسيط مسمى. | ||
ويجب أن يأتي هذا | |||
كما يمكن للمصفوفة الناتجة أن تتضمّن | كما يمكن للمصفوفة الناتجة أن تتضمّن [[Ruby/Hash|جدول Hash]] في نهايتها إذا مُرّر هذا النوع عند الاستدعاء بعد جميع الوسائط الموضعية. <syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | gather_arguments 1, a: 2 # [1, {:a=>2}] تطبع | ||
gather_arguments 1, a: 2 # | </syntaxhighlight>إلّا أنّ هذه الحالة تحصل فقط عندما لا يعرّف التابع أيّ وسائط من نوع "الوسائط المسماة".<syntaxhighlight lang="ruby"> | ||
</syntaxhighlight> | |||
إلّا أنّ هذه الحالة تحصل فقط عندما لا يعرّف التابع أيّ | |||
<syntaxhighlight lang="ruby"> | |||
def gather_arguments_keyword(*positional, keyword: nil) | def gather_arguments_keyword(*positional, keyword: nil) | ||
p positional: positional, keyword: keyword | p positional: positional, keyword: keyword | ||
end | end | ||
gather_arguments_keyword 1, 2, three: 3 | gather_arguments_keyword 1, 2, three: 3 | ||
#=> unknown keyword: three (ArgumentError):تسبب ظهور خطأ | |||
لاحظ أيضًا أنّ استخدام الرمز * وحده يسبب تجاهل أيّ معاملات. | # لاحظ أيضًا أنّ استخدام الرمز * وحده يسبب تجاهل أيّ معاملات. | ||
def ignore_arguments(*) | def ignore_arguments(*) | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== | ==الوسائط المسماة== | ||
الوسائط المسماة تشبه في آلية عملها الوسائط الموضعية ذات القيم الافتراضية:<syntaxhighlight lang="ruby"> | |||
<syntaxhighlight lang="ruby"> | |||
def add_values(first: 1, second: 2) | def add_values(first: 1, second: 2) | ||
first + second | first + second | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>يمكن قبول أيّ عدد من الوسائط المسماة باستخدام الرمز <code>**</code> قبل اسم الوسيط:<syntaxhighlight lang="ruby"> | ||
يمكن قبول أيّ عدد من | |||
<syntaxhighlight lang="ruby"> | |||
def gather_arguments(first: nil, **rest) | def gather_arguments(first: nil, **rest) | ||
p first, rest | p first, rest | ||
end | end | ||
gather_arguments first: 1, second: 2, third: 3 | gather_arguments first: 1, second: 2, third: 3 | ||
# {:second=>2, :third=>3} تطبع 1 ثم | |||
</syntaxhighlight> | </syntaxhighlight>عند استدعاء تابع مع وسائط مسماة، فمن الممكن لها أن تأتي ضمن أيّ ترتيب، إلّا أنّ الوسائط غير المعرفة مسبقًا ستسبب ظهور خطأ من النوع <code>[[Ruby/ArgumentError|ArgumentError]]</code>. | ||
عند استدعاء تابع | |||
وفي حال رغبتك باستخدام | وفي حال رغبتك باستخدام وسائط مسماة مع وسائط موضعية، فعليك أن تكتب جميع الوسائط الموضعية قبل أيّ وسيط مسمى. | ||
== | ==وسائط الكتلة البرمجية== | ||
يُميّز | يُميّز وسيط الكتلة البرمجيّة باستخدام الرمز <code>&</code>، ويجب أن يكون الأخير ضمن تسلسل الوسائط:<syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method(&my_block) | def my_method(&my_block) | ||
my_block.call(self) | my_block.call(self) | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>في أغلب الأحيان، يستخدم هذا النوع من الوسائط لتمرير كتلة برمجيّة إلى تابع آخر:<syntaxhighlight lang="ruby"> | ||
في أغلب | |||
<syntaxhighlight lang="ruby"> | |||
def each_item(&block) | def each_item(&block) | ||
@items.each(&block) | @items.each(&block) | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>إذا أردت فقط أن تنفّذ الكتلة البرمجيّة ولن تجري بالمقابل تعديلًا عليها أو إرسالها إلى تابع آخر، فيفضّل حينها أن تستخدم الكلمة المحجوزة <code>yield</code> دون تحديد وسيط معيّن. فالطريقة التالية تكافئ التابع الأوّل في هذه الفقرة:<syntaxhighlight lang="ruby"> | ||
إذا أردت فقط أن تنفّذ الكتلة البرمجيّة ولن | |||
<syntaxhighlight lang="ruby"> | |||
def my_method | def my_method | ||
yield self | yield self | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>وهناك فائدة أخرى على صعيد تحسين الأداء عند استخدام <code>yield</code> عوضًا عن الاستدعاء المباشر للكتلة؛ فعند إسناد وسيط كتلة برمجية إلى متغيّر، سيسبّب ذلك إنشاء كائن من النوع <code>[[Ruby/Proc|Proc]]</code> والذي سيبّب إيقاف تنفيذ الكتلة مؤقتًا. أمّا عند استخدام <code>yield</code>، فلن يُنشأ الكائن <code>[[Ruby/Proc|Proc]]</code> هذا بالأساس. | ||
وهناك فائدة أخرى على صعيد تحسين الأداء عند استخدام yield عوضًا عن الاستدعاء المباشر | |||
إذا كانت حاجتك إلى استخدام هذه الكتلة | إذا كانت حاجتك إلى استخدام هذه الكتلة قليلة، فبإمكانك حينئذٍ أن تستخدم <code>[[Ruby/Proc/new|Proc.new]]</code> لإنشاء <code>[[Ruby/Proc|proc]]</code> من الكتلة البرمجيّة والذي يمكن تمريره إلى التابع. انظر التوثيق الخاصّ بالتابع <code>[[Ruby/Proc/new|Proc.new]]</code> لمزيد من التفاصيل. | ||
== التعامل مع الاستثناءات == | ==التعامل مع الاستثناءات== | ||
تحتوي التوابع على آلية تعامل مع الاستثناءات ضمنية، فلست بحاجة لاستخدام begin - end للتعامل مع الاستثناء. فهذا المثال: | تحتوي التوابع على آلية [[Ruby/exceptions|تعامل مع الاستثناءات]] ضمنية، فلست بحاجة لاستخدام <code>begin - end</code> للتعامل مع الاستثناء. فهذا المثال: <syntaxhighlight lang="ruby"> | ||
<syntaxhighlight lang="ruby"> | |||
def my_method | def my_method | ||
begin | begin | ||
سطر 340: | سطر 301: | ||
end | end | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>يمكن كتابته بالشكل التالي:<syntaxhighlight lang="ruby"> | ||
يمكن كتابته بالشكل التالي: | |||
<syntaxhighlight lang="ruby"> | |||
def my_method | def my_method | ||
# شيفرة قد تسبب ظهور استثناء | # شيفرة قد تسبب ظهور استثناء | ||
سطر 348: | سطر 307: | ||
# التعامل مع الاستثناء | # التعامل مع الاستثناء | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight>إذا أردت تفادي استثناء في جزء محدد من التابع فقط، فاستخدم حينها <code>begin - end</code>. لمزيد من التفاصيل ارجع إلى الصفحة الخاصة [[Ruby/exceptions|بالتعامل مع الاستثناءات]]. | ||
إذا أردت تفادي استثناء | =المصادر= | ||
*[https://ruby-doc.org/core-2.5.1/doc/syntax/methods_rdoc.html صفحة Methods في توثيق روبي الرسمي.] | |||
[[تصنيف: Ruby]] | |||
[[تصنيف: Ruby Syntax]] |
المراجعة الحالية بتاريخ 14:19، 18 نوفمبر 2018
تتضمّن التوابع في لغة روبي الوظائف التي يقوم بها برنامجك. إليك هذا المثال لتعريف تابع بسيط:
def one_plus_one
1 + 1
end
تعريف التابع يتكوّن من الكلمة المحجوزة def
يتبعها اسم التابع، ثمّ جسم التابع، فالقيمة المعادة وفي النهاية الكلمة المحجوزة end
. فعند تنفيذ التابع في المثال السابق، ستُعاد القيمة 2. هذا القسم سيغطّي تعريف التّوابع. ارجع إلى توثيق استدعاء التوابع لتتعرف على الصيغ المستخدمة لذلك الغرض.
تسمية التوابع
يمكن أن تستخدم لاسم التابع أحد المعاملات، وإلا فعليك أن تبتدئه بحرف أبجديّ أو أيّ محرف من محارف لوحة المفاتيح (أيضًا تعرف باسم محارف البتات الثمانية أي كل محرف بحجم 8 بت). ويمكن للاسم أن يتضمن أحرفًا وأرقامًا وشرطة سفليّة (_)، أو أيّ محرف من محارف البتات الثمانية. ومن المعتاد أن تستخدم الشرطة السفليّة لتفصل بين الكلمات في أسماء التوابع التي تتضمن كلمات عدّة.
def method_name
puts "use underscores to separate words"
end
يجب أن تكتب البرامج بلغة روبي باستخدام مجموعات محارف متوافقة مع مجموعة المحارف US-ASCII مثل UTF-8 و ISO-8859-1. فإذا كان البتات الثمانية مضبوطة في مجموعات المحارف هذه، فهذا يدل على أنّ المحرف هو من المحارف الموسّعة، ولغة روبي تسمح أن تحتوي أسماء التوابع والمعرّفات الأخرى على تلك المحارف. إلا أنّ لغة روبي لا تسمح باستخدام بعض المحارف مثل ASCII NUL الذي رمزه \x00. إليك بعض الأمثلة عن التوابع التي تصلح تسميتها في لغة روبي:
def hello
"hello"
end
def こんにちは
puts "means hello in Japanese"
end
وعادة ما تكون أسماء التوابع متوافقة مع نظام US-ASCII كون الحروف الخاصة به متوفرة على جميع لوحات المفاتيح. ويمكن لأسماء التوابع أن تنتهي بعلامة التعجّب !
أو علامة الاستفهام ?
أو علامة المساواة =
.
إن التوابع المنتهية بعلامة تعجب تستدعى وتُنفّذ مثل أيّ تابع آخر، إلّا أنّها عادة ما تصنّف كتوابع خطرة. ففي مكتبة نواة لغة روبي يُعدّ التّابع خطيرًا إذا كان يغيّر من قيمة المتغيّر الذي يستقبله، ولذلك يُميّز بعلامة التعجّب في آخره.
وفي هذه المكتبة يوجد لكلّ تابع من هذا النّوع تابعًا آخر مقابلًا ليس خطيرًا أي أنّه لا يغيّر من قيمة المتغيّر الذي يستقبله، وهذه التّوابع يكون لها نفس التسمية إلا أنّها لا تنتهي بإشارة التّعجب.
أمّا المتعارف عليه بالنّسبة للتوابع التي تنتهي تسميتها بإشارة استفهام فهي التوابع التي تُرجع قيمة منطقيّة، لكنّها لا تعيد بالضّرورة القيمة true
أو false
، بل غالبًا ما تعيد كائنًا يعبّر عن true
أو قيمة الإيجاب.
والتوابع التي تنتهي بإشارة مساواة فهي توابع الإسناد؛ وبالنسبة لهذا النوع من التوابع، تُتجاهل القيمة المعادة وتُرجع معاملات التابع بدلًا منها.
فيما يلي أسماء التوابع المعبرة عن مختلف العمليات في لغة روبي، كلّ واحدة من هذه العمليات تقبل معاملًا واحدًا فقط. تجد بعد رمز العملية الاستخدام الشهير لها أو اسم العملية. لاحظ أنّك إن غيّرت ما تقوم به كلّ عمليّة فستسبّب لبسًا لدى المستخدم، إذ أنّ المتوقّع من إشارة الجمع أن تجمع، ومن إشارة الطرح أن تطرح، وهكذا. أضف إلى ذلك أنّك لن تتمكّن من تغيير أولويّة أيّ من هذه العمليات.
المعامل | العملية |
---|---|
+ | جمع |
- | طرح |
* | ضرب |
** | قوة |
/ | قسمة |
% | باقي القسمة، أو سلسلة % |
& | العملية AND |
^ | العملية XOR |
>> | إزاحة لليمين |
<< | إزاحة لليسار، أو إضافة |
== | اختبار المساواة |
=! | اختبار عدم المساواة |
=== | المساواة التامة |
~= | مطابقة النمط (ليس خاصًّا بالتعبيرات النظامية فحسب) |
~! | عدم مطابقة النمط |
<=> | المقارنة والمعروف أيضًا بمعامل سفينة الفضاء |
> | أصغر من |
=> | أصغر من أو يساوي |
< | أكبر من |
=< | أكبر من أو يساوي |
لأجل تعريف توابع أحادية تغيّر سلوك إشارة الجمع والطرح والضرب والنفي المنطقي، عليك أن تُتبع رمز العملية بالرمز @
مثل: +@
أو !@
كما في المثال التالي:
class C
def -@
puts "you inverted this object"
end
end
obj = C.new
-obj # "you inverted this object" يطبع
التوابع الأحادية لا تقبل أي معاملات. بالإضافة لذلك يمكن تعريف التوابع التي تستخدم للإشارة إلى العناصر وإسناد قيمٍ إليها بالشّكل []
أو []=
على التوالي وبالترتيب. وكلاهما بالإمكان أن يأخذ معاملًا واحدًا أو أكثر. ويمكن لتابع الإشارة للعناصر ألا يأخذ أيّ معامل.
class C
def [](a, b)
puts a + b
end
def []=(a, b, c)
puts a * b + c
end
end
obj = C.new
obj[2, 3] # "5" يطبع
obj[2, 3] = 4 # "10" يطبع
القيم المعادة
تُعيد التوابع بشكل افتراضيّ آخر تعبير برمجيّ يصل إليه التنفيذ في جسم التابع؛ في المثال أعلاه، التعبير الأخير (والوحيد) الذي نُفّذ كان عمليّة جمع بسيطة 1+1. ويمكن أيضًا استخدام الكلمة المحجوزة return
للتأكيد بأنّ يعيد التابع القيمة التي تليها.
def one_plus_one
return 1 + 1
end
كما يمكن استخدام كلمة return
لإنهاء تنفيذ التابع دون إكمال التعبيرات البرمجيّة التي تليها.
def two_plus_two
return 2 + 2
1 + 1 # لا يتمّ تنفيذ هذا السطر أبدًا
end
لاحظ أنّه - كما أشرنا سابقًا - في حالة توابع الإسناد، فإنّ القيمة المعادة تُتجاهل ويعيد التابع بدلًا منها المعامل الذي مُرّر إليه:
def a=(value)
return 1 + value
end
p(self.a = 5) # تطبع5
أمّا القيمة المعادة فترجع فقط في حالة استدعاء التابع بشكل مباشر:
p send(:a=, 5) # تطبع 6
النطاق
الصيغة النظامية لتعريف تابع:
def my_method
# ...
end
وبهذه الطريقة تضيف تابعًا إلى صنف (class). كما يمكنك تعريف تابع لأغراض صنف معين وذلك بإضافة كلمة class:
class C
def my_method
# ...
end
end
كما يمكن تعريف تابع لكائن آخر. وتستطيع تعريف تابع للصنف نفسه (وليس للكائنات المتفرعة عنه) كالتالي:
class C
def self.my_method
# ...
end
end
وهذه الطريقة تُعد حالة خاصة من إحدى قواعد الصيغة في لغة روبي، وهي القدرة على إضافة تابع لأيّ كائن. وبما أنّ الأصناف بحدّ ذاتها هي نوع من الكائنات، فبالإمكان ببساطة إضافة تابع إلى كائن الصنف وفيما يلي صيغة إضافة تابع إلى كائن ما:
greeting = "Hello"
def greeting.broaden
self + ", world!"
end
greeting.broaden # تعيد "Hello, world!"
كلمة self
هي كلمة محجوزة في اللغة تشير إلى الغرض الحالي من وجهة نظر مفسّر اللغة، فهي تسهّل تعريف تابع الصنف في المثال السابق.
def String.hello
"Hello, world!"
end
تعريف التابع بهذا الشكل يسمى "التابع المنفرد" (singleton method). فالتابع broaden
في المثال السابق موجود في الكائن greeting
فحسب، ولن تجده في أيّ متغيّر آخر من نوع السلسلة النصية string
.
إعادة التعريف
عندما يصادف مفسّر لغة روبي كلمة def
قبل اسم تابع معرّف مسبقًا فإنّه لا يعدّ ذلك خطأ وإنّما يعيد تعريف هذا التابع. وهذا ما يسمّى بإعادة التعريف (Overriding). إلّا أنّ هذه الإمكانيّة في لغة روبي تُعدّ خطرة ولا يستحسن استخدامها بشكل متكّرر، إلا في حالة توسيع أصناف اللغة الأساسية (core classes)، لأنّها قد تؤدي إلى نتائج غير معروفة. خذ على سبيل المثال تسلسل الأوامر التالي:
>> "43".to_i
=> 43
>> class String
>> def to_i
>> 42
>> end
>> end
=> nil
>> "43".to_i
=> 42
هذا سيسبب بكلّ تأكيد تخريبًا لأيّ شيفرة تستخدم التابع to_i
من الصنف String
لاستخلاص أعدادٍ من سلسلة نصية.
وسائط التوابع
يمكن للتابع أن يقبل وسائط وتكون مكتوبة على التتالي بعد اسم التابع:
def add_one(value)
value + 1
end
عند استدعاء التابع add_one
، يجب على المستخدم أن يمرّر له وسيطًا، وهذا الوسيط هو متغيّر محليّ ضمن جسم التابع. ففي المثال السابق، يضيف التابع واحدًا إلى هذا الوسيط الذي مُرّر إليه، ويُعيد الناتج. فإذا أُعطي التابع 1 سيعيد 2.
والأقواس المحيطة بالوسائط اختيارية ويمكن حذفها:
def add_one value
value + 1
end
وإذا كان لديك أكثر من وسيط، فافصل بينها بفواصل:
def add_values(a, b)
a + b
end
فعند الاستدعاء، يجب تمرير الوسائط بنفس الترتيب؛ بعيارة أخرى، يمكن القول أنّ الوسائط حساسة للترتيب.
القيم الافتراضية
يمكن أن تحصل الوسائط على قيم افتراضية:
def add_values(a, b = 1)
a + b
end
ولا يشترط أن تكون القيمة الافتراضية في بداية أو نهاية الوسائط، إلّا أن الوسائط ذات القيم الافتراضية يجب أن تجمّع معًا، فالمثال التالي مقبول:
def add_values(a = 1, b = 2, c)
a + b + c
end
أما هذا المثال، فسيعطي الخطأ SyntaxError
:
def add_values(a = 1, b, c = 1)
a + b + c
end
تفكيك المصفوفة
يمكنك تفكيك مصفوفة (أوس استخراج القيم منها) باستخدام أقواس مضاعفة في معاملات التابع:
def my_method((a, b))
p a: a, b: b
end
my_method([1, 2])
هذا المثال يطبع:
{:a=>1, :b=>2}
ويُتجاهل كلّ عنصر في المصفوفة زائد على عدد الوسائط.
def my_method((a, b))
p a: a, b: b
end
my_method([1, 2, 3])
وهذا المثال له نفس نتيجة المثال السابق.
يمكنك استخدام الرمز *
لتحصيل الوسائط المتبقية أيًا كان عددها في المصفوفة؛ فالمثال التالي يفصل المصفوفة ليسند أول عنصر منها في الوسيط الأول، والباقي يسنده كمصفوفة إلى الوسيط الثاني:
def my_method((a, *b))
p a: a, b: b
end
my_method([1, 2, 3])
هذا المثال يطبع:
{:a=>1, :b=>[2, 3]}
أيّ وسيط يستجيب للتابع to_ary
يمكن استخدامه في عملية التفكيك هذه. فإذا كان لديك كائن آخر تريد أن تفكّكه بنفس الطريقة، فعليك أن تعرّف له التابع to_ary
الخاص به.
يمكنك استخدام أقواس ضمنية لتفكيك مصفوفة مُرّرت كوسيط، لكن إذا لم يكن الوسيط المقابل له من نوع مصفوفة، فسوف يُسند هذا الوسيط إلى الوسيط الأول ضمن قوسي التفكيك، بينما تأخذ بقية الوسائط القيمة nil
:
def my_method(a, (b, c), d)
p a: a, b: b, c: c, d: d
end
my_method(1, 2, 3)
هذا المثال يطبع:
{:a=>1, :b=>2, :c=>nil, :d=>3}
كما بإمكانك تضمين عمليات التفكيك داخل بعضها بأي شكل:
def my_method(((a, b), c))
# ...
end
الوسائط التي من النوع: مصفوفة وجدول Hash
إضافة الرمز *
في بداية اسم الوسيط يسبب تحويل جميع الوسائط الإضافية إلى مصفوفة:
def gather_arguments(*arguments)
p arguments
end
gather_arguments 1, 2, 3 # [1, 2, 3] تطبع
ويجب أن يأتي هذا الوسيط في آخر الوسائط الموضعية وعليه أن يسبق أيّ وسيط مسمى. كما يمكن للمصفوفة الناتجة أن تتضمّن جدول Hash في نهايتها إذا مُرّر هذا النوع عند الاستدعاء بعد جميع الوسائط الموضعية.
gather_arguments 1, a: 2 # [1, {:a=>2}] تطبع
إلّا أنّ هذه الحالة تحصل فقط عندما لا يعرّف التابع أيّ وسائط من نوع "الوسائط المسماة".
def gather_arguments_keyword(*positional, keyword: nil)
p positional: positional, keyword: keyword
end
gather_arguments_keyword 1, 2, three: 3
#=> unknown keyword: three (ArgumentError):تسبب ظهور خطأ
# لاحظ أيضًا أنّ استخدام الرمز * وحده يسبب تجاهل أيّ معاملات.
def ignore_arguments(*)
end
الوسائط المسماة
الوسائط المسماة تشبه في آلية عملها الوسائط الموضعية ذات القيم الافتراضية:
def add_values(first: 1, second: 2)
first + second
end
يمكن قبول أيّ عدد من الوسائط المسماة باستخدام الرمز **
قبل اسم الوسيط:
def gather_arguments(first: nil, **rest)
p first, rest
end
gather_arguments first: 1, second: 2, third: 3
# {:second=>2, :third=>3} تطبع 1 ثم
عند استدعاء تابع مع وسائط مسماة، فمن الممكن لها أن تأتي ضمن أيّ ترتيب، إلّا أنّ الوسائط غير المعرفة مسبقًا ستسبب ظهور خطأ من النوع ArgumentError
.
وفي حال رغبتك باستخدام وسائط مسماة مع وسائط موضعية، فعليك أن تكتب جميع الوسائط الموضعية قبل أيّ وسيط مسمى.
وسائط الكتلة البرمجية
يُميّز وسيط الكتلة البرمجيّة باستخدام الرمز &
، ويجب أن يكون الأخير ضمن تسلسل الوسائط:
def my_method(&my_block)
my_block.call(self)
end
في أغلب الأحيان، يستخدم هذا النوع من الوسائط لتمرير كتلة برمجيّة إلى تابع آخر:
def each_item(&block)
@items.each(&block)
end
إذا أردت فقط أن تنفّذ الكتلة البرمجيّة ولن تجري بالمقابل تعديلًا عليها أو إرسالها إلى تابع آخر، فيفضّل حينها أن تستخدم الكلمة المحجوزة yield
دون تحديد وسيط معيّن. فالطريقة التالية تكافئ التابع الأوّل في هذه الفقرة:
def my_method
yield self
end
وهناك فائدة أخرى على صعيد تحسين الأداء عند استخدام yield
عوضًا عن الاستدعاء المباشر للكتلة؛ فعند إسناد وسيط كتلة برمجية إلى متغيّر، سيسبّب ذلك إنشاء كائن من النوع Proc
والذي سيبّب إيقاف تنفيذ الكتلة مؤقتًا. أمّا عند استخدام yield
، فلن يُنشأ الكائن Proc
هذا بالأساس.
إذا كانت حاجتك إلى استخدام هذه الكتلة قليلة، فبإمكانك حينئذٍ أن تستخدم Proc.new
لإنشاء proc
من الكتلة البرمجيّة والذي يمكن تمريره إلى التابع. انظر التوثيق الخاصّ بالتابع Proc.new
لمزيد من التفاصيل.
التعامل مع الاستثناءات
تحتوي التوابع على آلية تعامل مع الاستثناءات ضمنية، فلست بحاجة لاستخدام begin - end
للتعامل مع الاستثناء. فهذا المثال:
def my_method
begin
# شيفرة قد تسبب ظهور استثناءات
rescue
# التعامل مع الاستثناء
end
end
يمكن كتابته بالشكل التالي:
def my_method
# شيفرة قد تسبب ظهور استثناء
rescue
# التعامل مع الاستثناء
end
إذا أردت تفادي استثناء في جزء محدد من التابع فقط، فاستخدم حينها begin - end
. لمزيد من التفاصيل ارجع إلى الصفحة الخاصة بالتعامل مع الاستثناءات.