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

من موسوعة حسوب
ط تصحيح التنسيق
ط مراجعة وتدقيق.
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE: الإسناد في لغة روبي}}</noinclude>
= الإسناد في لغة روبي =
لكي نسند شيء في لغة روبي، نستخدم رمز المساواة <code>=</code>؛ ففي المثال التّالي، يُسنَد العدد 5 إلى المتغيّر <code>v</code> المحلّي:<syntaxhighlight lang="ruby">
للإسناد في لغة روبي نستخدم رمز المساواة =، ففي المثال التّالي يُسنَد الرّقم 5 إلى المتغيّر المحلّي v:<syntaxhighlight lang="ruby">
v = 5
v = 5
</syntaxhighlight>فالإسناد يُنشئ متغيّرًا محلّيًا جديدًا إذا لم يكن قد عُرِّفَ من قبل.
</syntaxhighlight>فالإسناد يُنشئ متغيّرًا محلّيًا جديدًا إذا لم يكن قد عُرِّفَ من قبل.
==أسماء المتغيرات المحلية==
اسم المتغيّر المحلّي يجب أن يبدأ بحرف صغير من مجموعة المحارف [[Arduino/asciichart|US-ASCII]] أو من مجموعة المحارف التي تُمثَّل باستخدام ثمان بتات ثنائيّة. وبشكلٍ عام، فإنّ أسماء المتغيّرات المحلّية متوافقة مع [[Arduino/asciichart|US-ASCII]] كون الأزرار التي تستخدم لكتابتها موجودة في جميع لوحات المفاتيح.


== أسماء المتغيّرات المحليّة ==
عمومًا، جميع البرامج المكتوبة بلغة روبي يجب أن تستخدم محارفًا متوافقة مع مجموعة المحارف [[Arduino/asciichart|US-ASCII]]. في مجموعات كهذه من المحارف، إذا كان البت الثامن بقيمة 1 فهذا يدلّ على أنّ المحرف ينتمي للمحارف الموسّعة (extended character)، ولغة روبي تسمح أن تحتوي أسماء المتغيّرات هذا النوع من المحارف.
اسم المتغيّر المحلّي يجب أن يبدأ بحرف صغير من مجموعة المحارف US-ASCII أو من مجموعة المحارف التي تُمثَّل باستخدام ثمان خانات ثنائيّة 8-bits. وبشكلٍ عام فإنّ أسماء المتغيّرات المحلّية متوافقة مع US-ASCII كون الأزرار التي تستخدم لكتابتها موجودة في جميع لوحات المفاتيح.
 
(عمومًا جميع البرامج المكتوبة بلغة روبي يجب أن تستخدم محارفًا متوافقة مع مجموعة المحارف US-ASCII. في مجموعات محارف كهذه، إذا كان البت الثامن بقيمة 1 فهذا يدلّ على أنّ المحرف ينتمي للمحارف الموسّعة extended character، ولغة روبي تسمح أن تحتوي أسماء المتغيّرات هذا النوع من المحارف.)
 
كما يُمكن لاسم المتحوّل أن يحتوي على حروفًا وأرقامًا ورمز الشرطة السفليّة underscore "_".


== نطاق المتغيّرات المحليّة ==
كما يُمكن لاسم المتحوّل أن يحتوي على حروفٍ وأرقامٍ ورمز الشرطة السفليّة (underscore) "_".
==نطاق المتغيرات المحلية==
بمجرّد أن يتمّ إسناد قيمة إلى المتغيّر المحلّيّ فكلّ استخدامات اسم هذا المتغيّر ضمن النطاق نفسه سيتمّ اعتبارها متغيّرات محليّة. وإليك هذا المثال:<syntaxhighlight lang="ruby">
بمجرّد أن يتمّ إسناد قيمة إلى المتغيّر المحلّيّ فكلّ استخدامات اسم هذا المتغيّر ضمن النطاق نفسه سيتمّ اعتبارها متغيّرات محليّة. وإليك هذا المثال:<syntaxhighlight lang="ruby">
1.times do
1.times do
سطر 22: سطر 19:
local variables in the block: a
local variables in the block: a
no local variables outside the block
no local variables outside the block
</syntaxhighlight>
</syntaxhighlight>بما أنّ الكتلة البرمجيّة <code>block</code> تنشئ نطاقًا جديد فلن يكون من الممكن استخدام أي متغيّر محليّ يُنشَأ ضمن هذا النطاق في النطاقات الأخرى خارجه. لكن يُمكن للمتغيّرات المعرّفة في نطاق ما أن تُستخدم في النّطاقات الأخرى المتضمّنة فيه كالتّالي:<syntaxhighlight lang="ruby">
 
بما أنّ الكتلة البرمجيّة block تنشئ نطاقًا جديد فلن يكون من الممكن استخدام أي متغيّر محليّ يُنشَأ ضمن هذا النطاق في النطاقات الأخرى خارجه. لكن يُمكن للمتغيّرات المعرّفة في نطاق ما أن تُستخدم في النّطاقات الأخرى المتضمّنة فيه كالتّالي:<syntaxhighlight lang="ruby">
a = 0
a = 0
1.times do
1.times do
سطر 31: سطر 26:
</syntaxhighlight>وتكون النتيجة طباعة التّالي:<syntaxhighlight lang="text">
</syntaxhighlight>وتكون النتيجة طباعة التّالي:<syntaxhighlight lang="text">
local variables: a
local variables: a
</syntaxhighlight>
</syntaxhighlight>ومن جهة أخرى، قد تودّ أن تعزل المتغيّرات المحليّة المعرّفة ضمن كتلة برمجيّة عن النّطاق الخارجيّ الذي يتضمنّها، في هذه الحالة عليك كتابة هذه المتغيّرات ضمن الكتلة البرمجيّة وكتابة فاصلة منقوطة بعد هذه المتغيّرات. لمثال على ذلك ارجع إلى التوثيق الخاص باستدعاء التوابع، واقرأ فقرة المتغيّرات المحليّة ضمن الكتل البرمجيّة.
 
ومن جهة أخرى، قد تودّ أن تعزل المتغيّرات المحليّة المعرّفة ضمن كتلة برمجيّة عن النّطاق الخارجيّ الذي يتضمنّها، في هذه الحالة عليك كتابة هذه المتغيّرات ضمن الكتلة البرمجيّة وكتابة فاصلة منقوطة بعد هذه المتغيّرات. لمثال على ذلك ارجع إلى التوثيق الخاص باستدعاء التوابع، واقرأ فقرة المتغيّرات المحليّة ضمن الكتل البرمجيّ.
 
انظر أيضًا فقرة النواة-المتغيّرات المحليّة، لكن انتبه إلى أنّ الحلقات من نوع for لا تنشئ نطاقًا خاصًّا بها كما هو الحال في الكتل البرمجيّة.


== التوابع والمتغيّرات المحليّة ==
انظر أيضًا توثيق التابع [[Ruby/Kernel/local variables|<code>Kernel.local_variables</code>]]، لكن انتبه إلى أنّ الحلقات من نوع <code>for</code> لا تنشئ نطاقًا خاصًّا بها كما هو الحال في الكتل البرمجيّة.
أسماء المتغيّرات المحليّة والتوابع في لغة روبي متماثلة تقريبًا. فإذا عرّفت اسمًا دون أن تسندَ إليه أيّ قيمة فسيُعدّ في اللّغة على أنّه تابع. وبمجرّد أن تُسند إليه قيمة فسيُعدّ متغيّرًا.
==التوابع والمتغيرات المحلية==
أسماء المتغيّرات المحليّة والتوابع في لغة روبي متماثلة تقريبًا. فإذا عرّفت اسمًا دون أن تسندَ إليه أيّ قيمة فسيُعدّ في لغة روبي على أنّه تابع. وبمجرّد أن تُسند إليه قيمة فسيُعدّ متغيّرًا.


يُنشَأ المتغيّر المحليّ عندما يمرّ مُفسِّر اللّغة parser على عمليّة الإسناد، وليس عندما تقع هذه العمليّة بالفعل، كما في المثال التّالي:<syntaxhighlight lang="ruby">
يُنشَأ المتغيّر المحليّ عندما يمرّ مُفسِّر روبي على عمليّة الإسناد، وليس عندما تقع هذه العمليّة بالفعل، كما في المثال التّالي:<syntaxhighlight lang="ruby">
a = 0 if false # لا يحصل الإسناد هنا
a = 0 if false # لا يحصل الإسناد هنا
p local_variables # يطبع [:a]
p local_variables # يطبع [:a]
سطر 46: سطر 38:
</syntaxhighlight>هذا التشابه بين أسماء المتغيّرات والتوابع قد يؤدّي في بعض الأحيان إلى صعوبة في فهم الشيفرة، فعلى سبيل المثال:<syntaxhighlight lang="ruby">
</syntaxhighlight>هذا التشابه بين أسماء المتغيّرات والتوابع قد يؤدّي في بعض الأحيان إلى صعوبة في فهم الشيفرة، فعلى سبيل المثال:<syntaxhighlight lang="ruby">
def big_calculation
def big_calculation
 42 # تظاهر بأنّها عمليّة تأخذ الكثير من الوقت
 42 # تتظاهر بأنّها عمليّة تأخذ الكثير من الوقت
end
end
big_calculation = big_calculation()
big_calculation = big_calculation()
</syntaxhighlight>أيّ إشارة هنا إلى big_calculation ستُعدّ على أنّها متغيّر محليّ وسيُحتفَظ بها في الذاكرة المخبئة cache. وإذا أردت بدلًا من ذلك استدعاء التابع ذي الاسم نفسه فعليك أن تكتب self.big_calculatoin.
</syntaxhighlight>أيّ إشارة هنا إلى <code>big_calculation</code> ستُعدّ على أنّها متغيّر محليّ وسيُحتفَظ بها في الذاكرة المخبئة (cache). وإذا أردت بدلًا من ذلك استدعاء التابع ذي الاسم نفسه فعليك أن تكتب <code>self.big_calculatoin</code>.


يمكنك أيضًا أن تُؤكّد على استدعاء التابع وذلك باستخدام أقواس فارغة كما يظهر في المثال، أو باستخدام مستقبِل محدّد مثل self. لكنّ الطّريقة الثّانية قد تسبب ظهور خطأ NameError إذا كان التابع غير متاح للاستدعاء العام (أي أنه ليس تابع عام).
يمكنك أيضًا أن تُؤكّد على استدعاء التابع وذلك باستخدام أقواس فارغة كما يظهر في المثال، أو باستخدام مستقبِل محدّد مثل <code>self</code>. لكنّ الطّريقة الثّانية قد تسبب ظهور الخطأ <code>[[Ruby/NameError|NameError]]</code> إذا كان التابع غير متاح للاستدعاء العام (أي أنه ليس تابعًا عامًّا).


وهناك حالة أخرى شائعة قد تسبّب التباسًا وتحصل عند استخدام if كالتّالي:<syntaxhighlight lang="ruby">
وهناك حالة أخرى شائعة قد تسبّب التباسًا وتحصل عند استخدام <code>if</code> كالتّالي:<syntaxhighlight lang="ruby">
p a if a = 0.zero?
p a if a = 0.zero?
</syntaxhighlight>فبدلًا من طباعة "true" سيظهر خطأ NameError, undefined local variable or method 'a'. والسّبب في ذلك يعود إلى أنّ اللغة ترى المتغير a الذي قبل if أوّلًا قبل المتغير a الآخر وتحسب أنّك تريد استدعاء تابع، ثمّ إذا مرّت على المتغير a الآخر فستفترض أنّك تريد الإشارة إلى تابع محليّ.
</syntaxhighlight>فبدلًا من طباعة "true" سيظهر الخطأ "NameError, undefined local variable or method 'a'. والسّبب في ذلك يعود إلى أنّ روبي ترى المتغير <code>a</code> الذي قبل <code>if</code> أوّلًا قبل المتغير <code>a</code> الآخر وتحسب أنّك تريد استدعاء تابع، ثمّ إذا مرّت على المتغير <code>a</code> الآخر فستفترض أنّك تريد الإشارة إلى تابع محليّ.


هذا اللبس يحصل لأنّ تنفيذ العبارة البرمجيّة يحصل بعكس الترتيب المنشود، فالإسناد يتمّ أوّلًا ثمّ يحصل استدعاء لتابع غير موجود.
هذا اللبس يحصل لأنّ تنفيذ العبارة البرمجيّة يحصل بعكس الترتيب المنشود، فالإسناد يتمّ أوّلًا ثمّ يحصل استدعاء لتابع غير موجود.
==متغيرات النسخة (Instance Variables)==
هي متغيّرات تُشارَك عبر كلّ التوابعّ التابعة لنفس الكائن. هذه المتغيّرات يجب أن تبدأ بالرّمز <code>@</code>، وعدا ذلك فهي تتبع نفس القواعد في تسميّة المتغيّرات المحليّة. وطالما أنّها تبدأ بالرّمز <code>@</code> فيُمكن للحرف الثّاني أن يكون حرفًا كبيرًا (upper case).


== متغيّرات الحالة Instance Variables ==
وهذا مثال على استخدام متغيّرات النسخة:<syntaxhighlight lang="ruby">
وهي متغيّرات تُشارَك عبر كلّ التوابعّ التابعة لنفس الكائن. هذه المتغيّرات يجب أن تبدأ بالرّمز @، وعدا ذلك فهي تتبع نفس القواعد في تسميّة المتغيّرات المحليّة. وطالما أنّها تبدأ بالرّمز @ فيُمكن للحرف الثّاني أن يكون حرفًا كبيرًا (upper case).
 
وهذا مثال على استخدام متغيّرات الحالة:<syntaxhighlight lang="ruby">
class C
class C
 def initialize(value)
 def initialize(value)
سطر 75: سطر 66:
p object1.value # تطبع "some value"
p object1.value # تطبع "some value"
p object2.value # تطبع "other value"
p object2.value # تطبع "other value"
</syntaxhighlight>متغيّرات الحالة التي لم يتمّ تهيئتها بقيمة ابتدائيّة تأخذ قيمة nil تلقائيًّا. وإذا شغّلتَ روبي بوضع تفعيل التحذيرات (warnings) فسيظهر لك تنبيهًا عند كلّ محاولة لاستخدام متغيّر حالة لم تتم تهيئته.
</syntaxhighlight>متغيّرات النسخة التي لم يتمّ تهيئتها بقيمة ابتدائيّة تأخذ القيمة <code>nil</code> تلقائيًّا. وإذا شغّلتَ روبي بوضع تفعيل التحذيرات (warnings) فسيظهر لك تنبيهًا عند كلّ محاولة لاستخدام متغيّر حالة لم تتم تهيئته.
 
يمكن لتابع value أن يصل إلى القيمة التي ضُبِطَت في التابع initialize، وذلك فقط للكائن نفسه.


== متغيّرات الأصناف Class Variables ==
يمكن للتابع <code>value</code> أن يصل إلى القيمة التي ضُبِطَت في التابع <code>initialize</code>، وذلك فقط للكائن نفسه.
==متغيرات الصنف (Class Variables)==
وهي متغيّرات مشتركة بين الصنف والأصناف المتفرّعة منه والكائنات المتولّدة عنه.
وهي متغيّرات مشتركة بين الصنف والأصناف المتفرّعة منه والكائنات المتولّدة عنه.


يجب أن يبدأ متغيّر الصنف بالرمزين @@، وتتمة الاسم تتبع لنفس أسلوب تسمية متغيّرات الحالة.
يجب أن يبدأ متغيّر الصنف بالرمزين <code>@@</code>، وتتمة الاسم تتبع لنفس أسلوب تسمية متغيّرات الحالة.


مثال:<syntaxhighlight lang="ruby">
إليك هذا المثال:<syntaxhighlight lang="ruby">
class A
class A
 @@class_variable = 0
 @@class_variable = 0
سطر 106: سطر 96:
A value: 0
A value: 0
B value: 0
B value: 0
</syntaxhighlight>
</syntaxhighlight>وبالاستمرار مع نفس المثال، يمكننا تحديث قيمة المتغيّر باستخدام كائنٍ من أيّ من الصنفين، وستُشارك القيمة الجديدة بينهما:<syntaxhighlight lang="ruby">
 
وبالاستمرار مع نفس المثال، يمكننا تحديث قيمة المتغيّر باستخدام كائنٍ من أيّ من الصنفين، وستُشارك القيمة الجديدة بينهما:<syntaxhighlight lang="ruby">
puts "update A"
puts "update A"
a.update
a.update
سطر 131: سطر 119:
A value: 4
A value: 4
B value: 4
B value: 4
</syntaxhighlight>
</syntaxhighlight>عند محاولة الوصول إلى متغيّر صنف لم تتمّ تهيئته فسيظهر استثناء من نوع <code>[[Ruby/NameError|NameError]]</code>.


عند محاولة الوصول إلى متغيّر صنف لم تتمّ تهيئته فسيظهر استثناء من نوع NameError.
لاحظ أنّ الأصناف لديها أيضًا متغيّرات النسخة وذلك لأنّ الأصناف هي كائنات أيضًا، لذلك حاول ألّا تخلط بين متغيّرات الأصناف ومتغيّرات النسخة.
==المتغيرات العامة (Global Variables)==
المتغيّرات العامّة يمكن الوصول إليها في كلّ مكان وهي تبدأ بالرّمز <code>$</code> وباقي الاسم يتبع نفس أسلوب تسمية متغيّرات النسخة.


لاحظ أنّ الأصناف لديها أيضًا متغيّرات حالة وذلك لأنّ الأصناف هي كائنات كذلك، لذلك حاول ألّا تخلط بين متغيّرات الأصناف ومتغيّرات الحالة.
إليك المثال التالي:<syntaxhighlight lang="ruby">
 
== المتغيّرات العامّة Global Variables ==
المتغيّرات العامّة يمكن الوصول إليها في كلّ مكان وهي تبدأ بالرّمز $ وباقي الاسم يتبع نفس أسلوب تسمية متغيّرات الحالة.
 
مثال:<syntaxhighlight lang="ruby">
$global = 0
$global = 0
class C
class C
سطر 152: سطر 137:
C.new.my_method
C.new.my_method
puts "at top-level, $global: #{$global}, $other_global: #{$other_global}"
puts "at top-level, $global: #{$global}, $other_global: #{$other_global}"
</syntaxhighlight>والنتيجة:<syntaxhighlight lang="text">
</syntaxhighlight>والنتيجة التي يطبعها هي:<syntaxhighlight lang="text">
in a class: 0
in a class: 0
in a method: 0
in a method: 0
at top-level, $global: 1, $other_global: 3
at top-level, $global: 1, $other_global: 3
</syntaxhighlight>
</syntaxhighlight>المتغيّرات العامّة التي لا يتم تهيئتها تكون قيمتها <code>nil</code>.
 
المتغيّرات العامّة التي لا يتم تهيئتها تكون قيمتها nil.


هناك بعض المتغيّرات العامّة المعرّفة مسبقًا في لغة روبي والتي قد تؤدّي أدوارًا مختلفة حسب السّياق كما هو الحال بالنّسبة لمتغيّرات المطابقة في التعابير النمطية (regular expressions)، وأحيانًا يكون لهذه المتغيّرات العامّة تأثيرات جانبيّة عندما يتمّ الإسناد إليها. لمزيد من التّفاصيل راجع الدّليل الخاص بالمتغيّرات العامّة.
هناك بعض المتغيّرات العامّة المعرّفة مسبقًا في لغة روبي والتي قد تؤدّي أدوارًا مختلفة حسب السّياق كما هو الحال بالنّسبة لمتغيّرات المطابقة في [[Ruby/Regexp|التعابير النمطية]] (regular expressions)، وأحيانًا يكون لهذه المتغيّرات العامّة تأثيرات جانبيّة عندما يتمّ الإسناد إليها. لمزيد من التّفاصيل راجع توثيق المتغيّرات العامّة.
 
==توابع للإسناد؟==
== دوالّ الإسناد ==
يمكنك تعريف توابع تؤدّي دور عمليّة الإسناد كالتّالي:<syntaxhighlight lang="ruby">
يمكنك تعريف دوالّ تؤدّي دور عمليّة الإسناد كالتّالي:<syntaxhighlight lang="ruby">
class C
class C
 def value=(value)
 def value=(value)
سطر 171: سطر 153:
c = C.new
c = C.new
c.value = 42
c.value = 42
</syntaxhighlight>استخدام هذه التوابع تجعل ببرنامجك يظهر بشكل أجمل. ومعظم المبرمجين يستخدمون Module#attr_accessor عند الإسناد إلى متحوّل حالة:<syntaxhighlight lang="ruby">
</syntaxhighlight>استخدام هذه التوابع تجعل برنامجك يظهر بشكل أجمل. ومعظم المبرمجين يستخدمون [[Ruby/Module/attr accessor|<code>Module.attr_accessor</code>]] عند الإسناد إلى متغير نسخة:<syntaxhighlight lang="ruby">
class C
class C
   attr_accessor :value
   attr_accessor :value
end
end
</syntaxhighlight>
</syntaxhighlight>عند استخدام الإسناد باستخدام التوابع، فمن اللازم وجود مستقبِل؛ وفي حال عدم وجوده، فستفترض لغة روبي أنّك تُسند إلى متغيّر محليّ.<syntaxhighlight lang="ruby">
 
عند استخدام الإسناد باستخدام التوابع فمن اللازم وجود مستقبِل، وفي حال عدم وجوده فستفترض لغة روبي أنّك تقوم بالإسناد إلى متغيّر محليّ.<syntaxhighlight lang="ruby">
class C
class C
 attr_accessor :value
 attr_accessor :value
سطر 190: سطر 170:
local_variables: value
local_variables: value
@value: nil
@value: nil
</syntaxhighlight>
</syntaxhighlight>لذلك، فعند استخدام دوال الإسناد، عليك تحديد مستقبِل:<syntaxhighlight lang="ruby">
 
لذلك فعند استخدام دوال الإسناد، عليك تحديد مستقبِل:<syntaxhighlight lang="ruby">
class C
class C
 attr_accessor :value
 attr_accessor :value
سطر 206: سطر 184:
@value: 42
@value: 42
</syntaxhighlight>
</syntaxhighlight>
 
==الإسناد المختصر (Abbreviated Assignment)==
== الإسناد المختصر ==
يمكنك الجمع بين أكثر من معامل مع عملية الإسناد، فعلى سبيل المثال، يمكنك عمل التّالي:<syntaxhighlight lang="ruby">
يمكنك الجمع بين أكثر من معامل مع عملية الإسناد، فعلى سبيل المثال، يمكنك عمل التّالي:<syntaxhighlight lang="ruby">
a = 1
a = 1
سطر 216: سطر 193:
a = a + 2
a = a + 2
p a # تطبع 3
p a # تطبع 3
</syntaxhighlight>وعلى نفس المنوال، يمكنك استخدام هذه المعاملات أيضًا: +, -, *, /, %, **, &, |, ^, <<, >>
</syntaxhighlight>وعلى نفس المنوال، يمكنك استخدام هذه المعاملات أيضًا: <code>+</code>، <code>-</code>، <code>*</code>، <code>/</code>، <code>%</code>، <code>**</code>، <code>&</code>، <code>|</code>، <code>^</code>، <code><<</code>، <code>>></code>.


ومن الممكن أيضًا استخدام  =|| وفي هذه الحالة يتمّ الإسناد فقط إذا كانت القيمة nil أو false، وبالمثل يمكن استخدام =&& فيتمّ الإسناد فقط إذا لم تكن القيمة nil أو false.
ومن الممكن أيضًا استخدام <code>=||</code> وفي هذه الحالة يتمّ الإسناد فقط إذا كانت القيمة <code>nil</code> أو <code>false</code>، وبالمثل يمكن استخدام <code>=&&</code> فيتمّ الإسناد فقط إذا لم تكن القيمة <code>nil</code> أو <code>false</code>.


مثال:<syntaxhighlight lang="ruby">
اطلع على المثال التالي الذي يشرح ذلك:<syntaxhighlight lang="ruby">
a ||= 0
a ||= 0
a &&= 1
a &&= 1
p a # تطبع 1
p a # تطبع 1
</syntaxhighlight>لاحظ أنّ هذين المعاملين يكافئان a || a = 0 أكثر من a = a || 0
</syntaxhighlight>لاحظ أنّ هذين المعاملين يكافئان <code>a || a = 0</code> أكثر من <code>a = a || 0</code>.
 
==إسناد مصفوفات ضمنيًّا==
== إسناد المصفوفات ضمنيًّا ==
يمكنك إنشاء مصفوفة وإسنادها ضمن عمليّة الإسناد وذلك بكتابة العناصر متتالية يفصل بينها فواصل كالتّالي:<syntaxhighlight lang="ruby">
يمكنك إنشاء مصفوفة ضمن عمليّة الإسناد وذلك بكتابة العناصر متتالية يفصل بينها فواصل كالتّالي:<syntaxhighlight lang="ruby">
a = 1, 2, 3
a = 1, 2, 3
p a #[1, 2, 3] تطبع
p a #[1, 2, 3] تطبع
</syntaxhighlight>وهكذا يتمّ إنشاء مصفوفة ضمنيًّا.
</syntaxhighlight>وهكذا يتمّ إنشاء مصفوفة ضمنيًّا.


يمكنك استخدام الرمز * أو معامل "الفصل" لتفكيك مصفوفة أثناء عملية الإسناد. وهذا يشابه الإسناد المتعدد. مثال:<syntaxhighlight lang="ruby">
يمكنك استخدام المعامل <code>*</code> أو معامل "الفصل" لتفكيك مصفوفة أثناء عملية الإسناد. وهذا يشابه الإسناد المتعدد. ألقٍ نظرة على المثال التالي:<syntaxhighlight lang="ruby">
a = *[1, 2, 3]
a = *[1, 2, 3]
p a #[1, 2, 3] تطبع  
p a #[1, 2, 3] تطبع  
سطر 239: سطر 215:
p a #[1, 2, 3] تطبع  
p a #[1, 2, 3] تطبع  
</syntaxhighlight>
</syntaxhighlight>
 
==الإسناد المتعدّد==
== الإسناد المتعدّد ==
يمكنك في لغة روبي أن تسند عدّة قيم على الجانب الأيمن إلى عدّة متغيّرات على الجانب الأيسر كالتّالي:<syntaxhighlight lang="ruby">
يمكنك في لغة روبي أن تسند عدّة قيم على الجانب الأيمن إلى عدّة متغيّرات على الجانب الأيسر كالتّالي:<syntaxhighlight lang="ruby">
a, b = 1, 2
a, b = 1, 2
p a: a, b: b #{:a=>1, :b=>2} تطبع  
p a: a, b: b #{:a=>1, :b=>2} تطبع  
</syntaxhighlight>وبنفس الطريقة يمكنك استخدام الإسناد المتعدّد مع أيّ نوع من المتغيّرات، سواء كانت متغيّرات أصناف أو متغيّرات حالة أو متغيرات عامّة، وحتّى الإسناد باستخدام التوابع كما في المثال:<syntaxhighlight lang="ruby">
</syntaxhighlight>وبنفس الطريقة يمكنك استخدام الإسناد المتعدّد مع أيّ نوع من المتغيّرات، سواء كانت متغيّرات أصناف أو متغيّرات نسخة أو متغيرات عامّة، وحتّى الإسناد باستخدام التوابع كما في المثال:<syntaxhighlight lang="ruby">
def value=(value)
def value=(value)
 p assigned: value
 p assigned: value
سطر 255: سطر 230:
p new_value: new_value, old_value: old_value
p new_value: new_value, old_value: old_value
#{:new_value=>1, :old_value=>2} تطبع  
#{:new_value=>1, :old_value=>2} تطبع  
</syntaxhighlight>في حال وجود عدد من القيم على الجانب الأيمن أكثر من عدد المتغيّرات المسند إليها على الجانب الأيسر، فعندها يتمّ تجاهل القيم الزائدة:<syntaxhighlight lang="ruby">
</syntaxhighlight>في حال وجود عدد من القيم على الجانب الأيمن أكثر من عدد المتغيّرات التي ستُسند إليها على الجانب الأيسر، فعندها يتمّ تجاهل القيم الزائدة الموجودة على الجانب الأيمن:<syntaxhighlight lang="ruby">
a, b = 1, 2, 3
a, b = 1, 2, 3
p a: a, b: b #{:a=>1, :b=>2} تطبع  
p a: a, b: b #{:a=>1, :b=>2} تطبع  
</syntaxhighlight>يمكنك استخدام معامل الفصل * في الإسناد المتعدّد لتجمع عددًا من القيم في مصفوفة واحدة:<syntaxhighlight lang="ruby">
</syntaxhighlight>يمكنك استخدام المعامل <code>*</code> في الإسناد المتعدّد لتجميع عددٍ من القيم وإسنادها إلى متغير واحد:<syntaxhighlight lang="ruby">
a, *b = 1, 2, 3
a, *b = 1, 2, 3
p a: a, b: b #{:a=>1, :b=>[2, 3]} تطبع  
p a: a, b: b #{:a=>1, :b=>[2, 3]} تطبع  
سطر 265: سطر 240:
p a: a, b: b #{:a=>[1, 2], :b=>3} تطبع  
p a: a, b: b #{:a=>[1, 2], :b=>3} تطبع  
</syntaxhighlight>لكن لا يمكنك استخدامه إلّا مرّة واحدة في كلّ عمليّة إسناد.
</syntaxhighlight>لكن لا يمكنك استخدامه إلّا مرّة واحدة في كلّ عمليّة إسناد.
 
==تفكيك المصفوفات==
== تفكيك المصفوفات ==
كما أنّه بإمكانك تفكيك المصفوفات عند تمرير القيم إلى التوابع، فكذلك بالإمكان تفكيك المصفوفة عند الإسناد وذلك باستخدام الأقواس المنحنية <code>()</code> كالتّالي:<syntaxhighlight lang="ruby">
كما أنّه بإمكانك تفكيك المصفوفات عند تمرير القيم إلى التوابع، فكذلك بالإمكان تفكيك المصفوفة عند الإسناد وذلك باستخدام الأقواس المنحنية () كالتّالي:<syntaxhighlight lang="ruby">
(a, b) = [1, 2]
(a, b) = [1, 2]
p a: a, b: b #{:a=>1, :b=>2} تطبع  
p a: a, b: b #{:a=>1, :b=>2} تطبع  
سطر 273: سطر 247:
a, (b, c) = 1, [2, 3]
a, (b, c) = 1, [2, 3]
p a: a, b: b, c: c #{:a=>1, :b=>2, :c=>3} تطبع  
p a: a, b: b, c: c #{:a=>1, :b=>2, :c=>3} تطبع  
</syntaxhighlight>وبما أنّ عمليّة التفكيك تعتبر عمليّة إسناد متعدّد في حد ذاتها، فبالتالي يمكنك استخدام المعامل * ضمنها كالتّالي:<syntaxhighlight lang="ruby">
</syntaxhighlight>وبما أنّ عمليّة التفكيك تعتبر عمليّة إسناد متعدّد في حد ذاتها، فبالتالي يمكنك استخدام المعامل <code>*</code> ضمنها كالتّالي:<syntaxhighlight lang="ruby">
a, (b, *c), *d = 1, [2, 3, 4], 5, 6
a, (b, *c), *d = 1, [2, 3, 4], 5, 6
p a: a, b: b, c: c, d: d
p a: a, b: b, c: c, d: d
#{:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]} تطبع  
#{:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]} تطبع  
</syntaxhighlight>
</syntaxhighlight>
 
==مصادر==
== مصادر ==
*[https://ruby-doc.org/core-2.5.1/doc/syntax/assignment_rdoc.html صفحة Assignment في توثيق روبي الرسمي.]
<span> </span>
[[تصنيف: Ruby]]
* [https://ruby-doc.org/core-2.5.1/doc/syntax/assignment_rdoc.html صفحة Assignment في توثيق روبي الرسمي.]
[[تصنيف: Ruby Syntax]]

مراجعة 09:50، 18 نوفمبر 2018

لكي نسند شيء في لغة روبي، نستخدم رمز المساواة =؛ ففي المثال التّالي، يُسنَد العدد 5 إلى المتغيّر v المحلّي:

v = 5

فالإسناد يُنشئ متغيّرًا محلّيًا جديدًا إذا لم يكن قد عُرِّفَ من قبل.

أسماء المتغيرات المحلية

اسم المتغيّر المحلّي يجب أن يبدأ بحرف صغير من مجموعة المحارف US-ASCII أو من مجموعة المحارف التي تُمثَّل باستخدام ثمان بتات ثنائيّة. وبشكلٍ عام، فإنّ أسماء المتغيّرات المحلّية متوافقة مع US-ASCII كون الأزرار التي تستخدم لكتابتها موجودة في جميع لوحات المفاتيح.

عمومًا، جميع البرامج المكتوبة بلغة روبي يجب أن تستخدم محارفًا متوافقة مع مجموعة المحارف US-ASCII. في مجموعات كهذه من المحارف، إذا كان البت الثامن بقيمة 1 فهذا يدلّ على أنّ المحرف ينتمي للمحارف الموسّعة (extended character)، ولغة روبي تسمح أن تحتوي أسماء المتغيّرات هذا النوع من المحارف.

كما يُمكن لاسم المتحوّل أن يحتوي على حروفٍ وأرقامٍ ورمز الشرطة السفليّة (underscore) "_".

نطاق المتغيرات المحلية

بمجرّد أن يتمّ إسناد قيمة إلى المتغيّر المحلّيّ فكلّ استخدامات اسم هذا المتغيّر ضمن النطاق نفسه سيتمّ اعتبارها متغيّرات محليّة. وإليك هذا المثال:

1.times do
 a = 1
 puts "local variables in the block: #{local_variables.join ", "}"
end
puts "no local variables outside the block" if local_variables.empty?

وتكون النتيجة طباعة التالي:

local variables in the block: a
no local variables outside the block

بما أنّ الكتلة البرمجيّة block تنشئ نطاقًا جديد فلن يكون من الممكن استخدام أي متغيّر محليّ يُنشَأ ضمن هذا النطاق في النطاقات الأخرى خارجه. لكن يُمكن للمتغيّرات المعرّفة في نطاق ما أن تُستخدم في النّطاقات الأخرى المتضمّنة فيه كالتّالي:

a = 0
1.times do
 puts "local variables: #{local_variables.join ", "}"
end

وتكون النتيجة طباعة التّالي:

local variables: a

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

انظر أيضًا توثيق التابع Kernel.local_variables، لكن انتبه إلى أنّ الحلقات من نوع for لا تنشئ نطاقًا خاصًّا بها كما هو الحال في الكتل البرمجيّة.

التوابع والمتغيرات المحلية

أسماء المتغيّرات المحليّة والتوابع في لغة روبي متماثلة تقريبًا. فإذا عرّفت اسمًا دون أن تسندَ إليه أيّ قيمة فسيُعدّ في لغة روبي على أنّه تابع. وبمجرّد أن تُسند إليه قيمة فسيُعدّ متغيّرًا.

يُنشَأ المتغيّر المحليّ عندما يمرّ مُفسِّر روبي على عمليّة الإسناد، وليس عندما تقع هذه العمليّة بالفعل، كما في المثال التّالي:

a = 0 if false # لا يحصل الإسناد هنا
p local_variables # يطبع [:a]
p a # يطبع nil

هذا التشابه بين أسماء المتغيّرات والتوابع قد يؤدّي في بعض الأحيان إلى صعوبة في فهم الشيفرة، فعلى سبيل المثال:

def big_calculation
 42 # تتظاهر بأنّها عمليّة تأخذ الكثير من الوقت
end
big_calculation = big_calculation()

أيّ إشارة هنا إلى big_calculation ستُعدّ على أنّها متغيّر محليّ وسيُحتفَظ بها في الذاكرة المخبئة (cache). وإذا أردت بدلًا من ذلك استدعاء التابع ذي الاسم نفسه فعليك أن تكتب self.big_calculatoin.

يمكنك أيضًا أن تُؤكّد على استدعاء التابع وذلك باستخدام أقواس فارغة كما يظهر في المثال، أو باستخدام مستقبِل محدّد مثل self. لكنّ الطّريقة الثّانية قد تسبب ظهور الخطأ NameError إذا كان التابع غير متاح للاستدعاء العام (أي أنه ليس تابعًا عامًّا).

وهناك حالة أخرى شائعة قد تسبّب التباسًا وتحصل عند استخدام if كالتّالي:

p a if a = 0.zero?

فبدلًا من طباعة "true" سيظهر الخطأ "NameError, undefined local variable or method 'a'. والسّبب في ذلك يعود إلى أنّ روبي ترى المتغير a الذي قبل if أوّلًا قبل المتغير a الآخر وتحسب أنّك تريد استدعاء تابع، ثمّ إذا مرّت على المتغير a الآخر فستفترض أنّك تريد الإشارة إلى تابع محليّ.

هذا اللبس يحصل لأنّ تنفيذ العبارة البرمجيّة يحصل بعكس الترتيب المنشود، فالإسناد يتمّ أوّلًا ثمّ يحصل استدعاء لتابع غير موجود.

متغيرات النسخة (Instance Variables)

هي متغيّرات تُشارَك عبر كلّ التوابعّ التابعة لنفس الكائن. هذه المتغيّرات يجب أن تبدأ بالرّمز @، وعدا ذلك فهي تتبع نفس القواعد في تسميّة المتغيّرات المحليّة. وطالما أنّها تبدأ بالرّمز @ فيُمكن للحرف الثّاني أن يكون حرفًا كبيرًا (upper case).

وهذا مثال على استخدام متغيّرات النسخة:

class C
 def initialize(value)
   @instance_variable = value
 end
 def value
   @instance_variable
 end
end
object1 = C.new "some value"
object2 = C.new "other value"
p object1.value # تطبع "some value"
p object2.value # تطبع "other value"

متغيّرات النسخة التي لم يتمّ تهيئتها بقيمة ابتدائيّة تأخذ القيمة nil تلقائيًّا. وإذا شغّلتَ روبي بوضع تفعيل التحذيرات (warnings) فسيظهر لك تنبيهًا عند كلّ محاولة لاستخدام متغيّر حالة لم تتم تهيئته.

يمكن للتابع value أن يصل إلى القيمة التي ضُبِطَت في التابع initialize، وذلك فقط للكائن نفسه.

متغيرات الصنف (Class Variables)

وهي متغيّرات مشتركة بين الصنف والأصناف المتفرّعة منه والكائنات المتولّدة عنه.

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

إليك هذا المثال:

class A
 @@class_variable = 0
 def value
   @@class_variable
 end
 def update
   @@class_variable = @@class_variable + 1
 end
end
class B < A
 def update
   @@class_variable = @@class_variable + 2
 end
end
a = A.new
b = B.new
puts "A value: #{a.value}"
puts "B value: #{b.value}"

وعند تنفيذه يطبع التّالي:

A value: 0
B value: 0

وبالاستمرار مع نفس المثال، يمكننا تحديث قيمة المتغيّر باستخدام كائنٍ من أيّ من الصنفين، وستُشارك القيمة الجديدة بينهما:

puts "update A"
a.update
puts "A value: #{a.value}"
puts "B value: #{b.value}"
puts "update B"
b.update
puts "A value: #{a.value}"
puts "B value: #{b.value}"
puts "update A"
a.update
puts "A value: #{a.value}"
puts "B value: #{b.value}"

وتكون النتيجة:

update A
A value: 1
B value: 1
update B
A value: 3
B value: 3
update A
A value: 4
B value: 4

عند محاولة الوصول إلى متغيّر صنف لم تتمّ تهيئته فسيظهر استثناء من نوع NameError.

لاحظ أنّ الأصناف لديها أيضًا متغيّرات النسخة وذلك لأنّ الأصناف هي كائنات أيضًا، لذلك حاول ألّا تخلط بين متغيّرات الأصناف ومتغيّرات النسخة.

المتغيرات العامة (Global Variables)

المتغيّرات العامّة يمكن الوصول إليها في كلّ مكان وهي تبدأ بالرّمز $ وباقي الاسم يتبع نفس أسلوب تسمية متغيّرات النسخة.

إليك المثال التالي:

$global = 0
class C
 puts "in a class: #{$global}"
 def my_method
   puts "in a method: #{$global}"
   $global = $global + 1
   $other_global = 3
 end
end
C.new.my_method
puts "at top-level, $global: #{$global}, $other_global: #{$other_global}"

والنتيجة التي يطبعها هي:

in a class: 0
in a method: 0
at top-level, $global: 1, $other_global: 3

المتغيّرات العامّة التي لا يتم تهيئتها تكون قيمتها nil.

هناك بعض المتغيّرات العامّة المعرّفة مسبقًا في لغة روبي والتي قد تؤدّي أدوارًا مختلفة حسب السّياق كما هو الحال بالنّسبة لمتغيّرات المطابقة في التعابير النمطية (regular expressions)، وأحيانًا يكون لهذه المتغيّرات العامّة تأثيرات جانبيّة عندما يتمّ الإسناد إليها. لمزيد من التّفاصيل راجع توثيق المتغيّرات العامّة.

توابع للإسناد؟

يمكنك تعريف توابع تؤدّي دور عمليّة الإسناد كالتّالي:

class C
 def value=(value)
   @value = value
 end
end
c = C.new
c.value = 42

استخدام هذه التوابع تجعل برنامجك يظهر بشكل أجمل. ومعظم المبرمجين يستخدمون Module.attr_accessor عند الإسناد إلى متغير نسخة:

class C
  attr_accessor :value
end

عند استخدام الإسناد باستخدام التوابع، فمن اللازم وجود مستقبِل؛ وفي حال عدم وجوده، فستفترض لغة روبي أنّك تُسند إلى متغيّر محليّ.

class C
 attr_accessor :value
 def my_method
   value = 42
   puts "local_variables: #{local_variables.join ", "}"
   puts "@value: #{@value.inspect}"
 end
end
C.new.my_method

وتكون النتيجة طباعة التّالي:

local_variables: value
@value: nil

لذلك، فعند استخدام دوال الإسناد، عليك تحديد مستقبِل:

class C
 attr_accessor :value
 def my_method
   self.value = 42
   puts "local_variables: #{local_variables.join ", "}"
   puts "@value: #{@value.inspect}"
 end
end
C.new.my_method

وتكون النتيجة:

local_variables:
@value: 42

الإسناد المختصر (Abbreviated Assignment)

يمكنك الجمع بين أكثر من معامل مع عملية الإسناد، فعلى سبيل المثال، يمكنك عمل التّالي:

a = 1
a += 2
p a # تطبع 3
وهذا يكافئ:
a = 1
a = a + 2
p a # تطبع 3

وعلى نفس المنوال، يمكنك استخدام هذه المعاملات أيضًا: +، -، *، /، %، **، &، |، ^، <<، >>.

ومن الممكن أيضًا استخدام =|| وفي هذه الحالة يتمّ الإسناد فقط إذا كانت القيمة nil أو false، وبالمثل يمكن استخدام =&& فيتمّ الإسناد فقط إذا لم تكن القيمة nil أو false.

اطلع على المثال التالي الذي يشرح ذلك:

a ||= 0
a &&= 1
p a # تطبع 1

لاحظ أنّ هذين المعاملين يكافئان a || a = 0 أكثر من a = a || 0.

إسناد مصفوفات ضمنيًّا

يمكنك إنشاء مصفوفة وإسنادها ضمن عمليّة الإسناد وذلك بكتابة العناصر متتالية يفصل بينها فواصل كالتّالي:

a = 1, 2, 3
p a #[1, 2, 3] تطبع

وهكذا يتمّ إنشاء مصفوفة ضمنيًّا. يمكنك استخدام المعامل * أو معامل "الفصل" لتفكيك مصفوفة أثناء عملية الإسناد. وهذا يشابه الإسناد المتعدد. ألقٍ نظرة على المثال التالي:

a = *[1, 2, 3]
p a #[1, 2, 3] تطبع

كما يمكنك الفصل في أيّ موضع على الجانب اليمينيّ من الإسناد:

a = 1, *[2, 3]
p a #[1, 2, 3] تطبع

الإسناد المتعدّد

يمكنك في لغة روبي أن تسند عدّة قيم على الجانب الأيمن إلى عدّة متغيّرات على الجانب الأيسر كالتّالي:

a, b = 1, 2
p a: a, b: b #{:a=>1, :b=>2} تطبع

وبنفس الطريقة يمكنك استخدام الإسناد المتعدّد مع أيّ نوع من المتغيّرات، سواء كانت متغيّرات أصناف أو متغيّرات نسخة أو متغيرات عامّة، وحتّى الإسناد باستخدام التوابع كما في المثال:

def value=(value)
 p assigned: value
end
self.value, $global = 1, 2 #{:assigned=>1} تطبع 
p $global # تطبع 2

كما يمكنك استخدام الإسناد المتعدّد للتّبديل بين قيمتي متغيّرين بشكل مباشر:

old_value = 1
new_value, old_value = old_value, 2
p new_value: new_value, old_value: old_value
#{:new_value=>1, :old_value=>2} تطبع

في حال وجود عدد من القيم على الجانب الأيمن أكثر من عدد المتغيّرات التي ستُسند إليها على الجانب الأيسر، فعندها يتمّ تجاهل القيم الزائدة الموجودة على الجانب الأيمن:

a, b = 1, 2, 3
p a: a, b: b #{:a=>1, :b=>2} تطبع

يمكنك استخدام المعامل * في الإسناد المتعدّد لتجميع عددٍ من القيم وإسنادها إلى متغير واحد:

a, *b = 1, 2, 3
p a: a, b: b #{:a=>1, :b=>[2, 3]} تطبع

ويمكنك وضع هذا المعامل في أيّ مكان على الجانب الأيسر:

*a, b = 1, 2, 3
p a: a, b: b #{:a=>[1, 2], :b=>3} تطبع

لكن لا يمكنك استخدامه إلّا مرّة واحدة في كلّ عمليّة إسناد.

تفكيك المصفوفات

كما أنّه بإمكانك تفكيك المصفوفات عند تمرير القيم إلى التوابع، فكذلك بالإمكان تفكيك المصفوفة عند الإسناد وذلك باستخدام الأقواس المنحنية () كالتّالي:

(a, b) = [1, 2]
p a: a, b: b #{:a=>1, :b=>2} تطبع

يمكنك أيضًا تفكيك المصفوفة ضمن عمليّة الإسناد المتعدّد:

a, (b, c) = 1, [2, 3]
p a: a, b: b, c: c #{:a=>1, :b=>2, :c=>3} تطبع

وبما أنّ عمليّة التفكيك تعتبر عمليّة إسناد متعدّد في حد ذاتها، فبالتالي يمكنك استخدام المعامل * ضمنها كالتّالي:

a, (b, *c), *d = 1, [2, 3, 4], 5, 6
p a: a, b: b, c: c, d: d
#{:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]} تطبع

مصادر