تعلم أساسيات البرمجة بلغة روبي – بنى البيانات، بعض التكرار، وقليل من المنطق

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

بالإضافة إلى هذه التدوينة، تتكون السلسلة من التدوينات التالية:

  1. تعلم أساسيات البرمجة بلغة روبي – مُقدِّمة
  2. تعلم أساسيات البرمجة بلغة روبي – أهلاً بالعالم!
  3. تعلم أساسيات البرمجة بلغة روبي – ثوابت، متغيرات، وأنواع بيانات
  4. تعلم أساسيات البرمجة بلغة روبي – البرمجة غرضية التوجه
  5. تعلم أساسيات البرمجة بلغة روبي – إرشادات لما بعد اﻷساسيات

ملاحظة: في هذا الدرس، سأستخدم النمط المبسّط من irb باستخدام الأمر التالي:

$ irb --simple-prompt

أولا: المزيد من أنواع وبنى البيانات

لنلقِ نظرة على بعض أنواع وبنى البيانات الموجودة في لغة روبي.

المصفوفات (Arrays)

باستخدام المصفوفات، يمكن تجميع عدة متغيرات (أو كائنات) في سلسلة تحت اسم واحد، ثم القيام بعدد من المهام كفرز عناصر المصفوفة أو تغيير قيم بعضها مثلا. هناك عدة طرق لإنشاء مصفوفة جديدة في روبي. دعونا نجرب طريقتين في irb:

>> greek_alphabet = Array.new
=> []
>> greek_alphabet = []
=> []

بإمكاننا التأكد من أن المصفوفة خالية باستخدام طريقة empty?:

>> greek_alphabet.empty?
=> true

المصفوفة الخالية تبدو مملة بعض الشيء. لننشئ مصفوفة جديدة، لكن دعونا نحدد عدد عناصرها بالإضافة إلى العنصر الافتراضي منذ البداية:

>> greek_alphabet = Array.new(4, '!')
=> ["!", "!", "!", "!"]

ماذا إذا أردنا أن تحتوي المصفوفة عناصر مختلفة؟

>> greek_alphabet = ['alpha', 'beta', 'gamma', 'delta']
=> ["alpha", "beta", "gamma", "delta"]

إذا، لدينا مصفوفة تحوي عدة عناصر. مالذي يمكننا فعله بها؟ هناك الكثير من الطرق الخاصة بمصفوفات روبي، لكننا سنتطرق لبعض منها. يمكننا معرفة حجم مصفوفة ما (عدد عناصرها) باستخدام أحد الطريقتين size وlength:

>> greek_alphabet.size
=> 4
>> greek_alphabet.length
=> 4

كما في العديد من لغات البرمجة الأخرى، يبدأ فهرس (index) أي مصفوفة من الرقم 0، بمعنى أنه إذا أردنا استرجاع العنصر الأول، فنستخدم الفهرس 0، وإذا أردنا استرجاع العنصر الثاني، فنستخدم الفهرس 1 وهكذا. لنجرب هذا في irb:

>> greek_alphabet[0]
=> "alpha"
>> greek_alphabet[2]
=> "gamma"

يمكننا القيام بالعكس، أي معرفة فهرس عنصر معين باستخدام طريقة index:

>> greek_alphabet.index('delta')
=> 3

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

>> mixed_array = ['delicious', 3.14, true]
=> ["delicious", 3.14, true]
>> mixed_array[-1]
=> true
>> mixed_array[-2]
=> 3.14
>> mixed_array[-3]
=> "delicious"
>> greek_alphabet[5] = "zeta"
=> "zeta"
>> greek_alphabet
=> ["alpha", "beta", "gamma", "delta", nil, "zeta"]

مالذي يمكننا فعله أيضا؟ حسنا، يمكننا فرز عناصر المصفوفة أو عكس ترتيبها:

>> primes = [7, 5, 11, 13, 3, 2]
=> [7, 5, 11, 13, 3, 2]
>> primes.sort
=> [2, 3, 5, 7, 11, 13]
>> primes.reverse
=> [2, 3, 13, 11, 5, 7]

ملاحظة: إذا قمنا بالتأكد من ترتيب عناصر المصفوفة بعد تنفيذ المثال أعلاه، سنجد أنه لم يتغير! السبب هو أن طريقتي sort وreverse لاتجريان أي تعديل على المصفوفة الأصلية، بل تعيدان مصفوفات جديدة بالترتيب المطلوب. من الممكن التعديل على المصفوفة الأصلية كما يلي:

>> primes.sort!
=> [2, 3, 5, 7, 11, 13]
>> primes
=> [2, 3, 5, 7, 11, 13]
>> primes.reverse!
=> [13, 11, 7, 5, 3, 2]
>> primes
=> [13, 11, 7, 5, 3, 2]

هذا العرف لا يقتصر على الطرق الخاصة بالمصفوفات فقط، بل هو مستخدم بكثرة في لغة روبي.

جداول التلبيد (Hashes)

[ملاحظة: اعتمدت على قاموس عرب آيز لتعريب مصطلح hash. هل يوجد تعريب آخر أفضل أو أوضح؟]
جداول التلبيد تشبه المصفوفات إلى حد بعيد. الفرق يكمن في أنه يمكن استخدام أي نوع من أنواع البيانات كفهرس لجدول التلبيد، وليس الأرقام فقط كما هي الحال في المصفوفات. يسمى الفهرس في جدول التلبيد بالمفتاح (key).
لنجرب المثال التالي في irb:

>> roman_numerals = { 'I' => 1, 'II' => 2, 'III' => 3, 'IV' => 4 }
=> {"II"=>2, "IV"=>4, "III"=>3, "I"=>1}
>> roman_numerals['IV']
=> 4

هناك العديد من الطرق الخاصة بجداول التلبيد في روبي، لكننا لن نناقشها هنا.

الرموز (Symbols)

الرموز هي أحد أنواع البيانات الخاصة في لغة روبي، وهي مستخدمة بكثرة في إطار Ruby on Rails. كل ما نحتاج معرفته في الوقت الحالي هو أن الرمز يبدأ بنقطتين رأسيّتين (:)، وأنه يمثل “ماسك مكان” أو معرّف. لنجرب مثالا عمليا على استخدام الرموز كمفاتيح في جداول التلبيد:

>> roman_numerals = { :I => 1, :II => 2, :III => 3, :IV => 4 }
=> {:I=>1, :II=>2, :III=>3, :IV=>4}
>> roman_numerals[:II]
=> 2

ثانياً: العوامل المنطقية

تدعم روبي العمليات المنطقية المعروفة والموجودة في معظم لغات البرمجة الأخرى. ناتج هذه العمليات هو إما true أو false (تذكروا: كل شيء في روبي هو عبارة عن كائن، حتى true وfalse!). لنجرب الأمثلة التالية في irb:

>> 1 < 2
=> true
>> 2 < = 3
=> true
>> 'ruby' == 'python'
=> false
>> (1 == 1) and (2 == 2)
=> true
>> (1 == 1) and (2 == 3)
=> false
>> (1 == 1) && (2 == 3)
=> false
>> (1 == 1) or (2 == 3)
=> true
>> (1 == 2) or (2 == 3)
=> false
>> (1 == 2) || (2 == 3)
=> false
>> not (1 == 2)
=> true
>> !(2 == 3)
=> true
>> not true
=> false

يمكن لمفسّر روبي أن ينتج قيمة منطقية من أي عبارة. لذلك، بإمكاننا مزج سلاسل نصية، أعداد، وحتى تواريخ في العبارات المنطقية. القاعدة بسيطة: false وnil ينتجان”خطأ”، وأي شيء آخر ينتج “صواب”. هذا يعني بأن العدد 0 ينتج “صواب”، مما قد يفاجئ المبرمجين بلغة C أو C++.

>> 'googol' == 10**100
=> false
>> 'ruby' and true
=> true
>> nil or false
=> false
>> 0 or nil
=> 0
>> 0 and nil
=> nil

ثالثاً: الجمل الشرطية

كأي لغة برمجة أخرى، تحتوي روبي جملا شرطية تمكّن المبرمج من تنفيذ عبارات معينة بناء على تحقق شرط (أو عدم تحققه). لنطّلع على بعض الأمثلة لعبارة if وelsif:

if number_of_open_tabs < = 5
  puts 'Light load.'
elsif number_of_open_tabs <= 10
  puts 'Medium load.'
elsif number_of_open_tabs <= 15
  puts 'Heavy load.'
else
  puts 'Take a bereak!'
end

يجدر ملاحظة أن الكلمة المفتاحية هي elsif – خمسة حروف – وليست elseif.

pi = 3.141; phi = 1.618
if phi < pi
  puts 'Keep in mind that Phi is less than Pi.'
end

من الممكن استخدام الصيغة التالية إذا كانت الشفرة التي نريد تنفيذها مكونة من عبارة واحدة:

puts 'Keep in mind that Phi is less than Pi.' if phi < pi

هناك أيضا عبارة unless، التي يمكن النظر إليها على أنها عبارة if منفية:

unless phi >= pi
  puts 'Keep in mind that Phi is less than Pi.'
end
puts 'Keep in mind that Phi is less than Pi.' unless phi >= pi

يفضّل عدم إساءة استخدام جملة unless، خصوصاً في الجمل الشرطية المعقدة، لأنها قد تربك الشخص الذي سيقرأ الشفرة البرمجية (بل إنها قد تربك كاتب الشفرة نفسه!).

رابعا: حلقات التكرار

تحتوي لغة روبي أيضاً على عدد من حلقات التكرار. أحدها هي حلقة while التقليدية:

greek_alphabet = ['alpha', 'beta', 'gamma', 'delta']
i = 0
while i < greek_alphabet.length
  puts greek_alphabet[i].capitalize
  i += 1
end
# Prints the following:
# Alpha
# Beta
# Gamma
# Delta

هناك أيضاً حلقة until. وكما أن عبارة unless هي عبارة if منفية، فحلقة until هي حلقة while منفية:

i = 0
until i > 4
 puts i
 i += 1
end
# Prints the following:
# 0
# 1
# 2
# 3
# 4

أخيراً، لننظر إلى حلقة times، وهي طريقة موجودة لدى أي كائن من النوع Integer:

5.times { |i| print i, ' ' } # Prints the following: 0 1 2 3 4

فائدة مهمة: القطع الشيفرية (Blocks)

هل لاحظتم شيئاً مميزاً في المثال الأخير أعلاه؟ الشيفرة الموجودة بين القوسين هي مثال لأحد أبرز مزايا لغة روبي: القطع الشفرية أو blocks. قد تبدو القطعة الشيفرية كمجرد مجموعة من العبارات البرمجية، لكنها في الحقيقة أكثر من ذلك بكثير. غالباً، تستخدم القطعة الشفرية كأسلوب لجلب عناصر بنية بيانات ما والمرور عليها عنصراً عنصراً. مثلا، بإمكاننا جلب عناصر المصفوفة greek_alphabet ومعالجة كل عنصر على حدة باستخدام طريقة each كالتالي:

greek_alphabet = ['alpha', 'beta', 'gamma', 'delta']
greek_alphabet.each do |element|
  puts element.capitalize
end
# Prints the following:
# Alpha
# Beta
# Gamma
# Delta

element هو الاسم الذي اخترناه للمتغيّر المحلي الذي يمثل العنصر الذي تتم معالجته حالياً. إذا وضعنا كل الشفرة السابقة في سطر واحد، يمكننا استخدام الأقواس بدلاً من do وend:

greek_alphabet.each { |element| puts element.capitalize }

تذكروا: هذا ليس هو الاستخدام الوحيد للقطع الشيفرية. سنعاود زيارة هذا الموضوع في درس قادم بإذن الله.

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

مقالات من مؤلف التدوينة

عدد التعليقات 3

  1. afi SYRIAN ARAB REPUBLIC Windows XP Internet Explorer 6.0
    Posted الخميس 14 مايو 2009 at 10:43 م | Permalink

    السلام عليكم
    بصراحة انا معجب بموقعك وبحييك عليه
    بس انو حقك علينا انو الواحد بيقرا بدون ما يكتب شي رد بس صدقني دوم بقول الله يعطيك العافية
    حابب اطلب مشورتك بموضوع بعد اذنك
    انا مهتم كبير بامن المعلومات والشبكات وعم افكر اتعلم لغة الروبي او البايثون
    وانا عندي خبرة جيدة بالبرمجة
    بدي تنصحني واذا سؤالي مو واضح فيا ريت اتقلي اوضح اكتر
    يعني الروبي مناسبة لتطبيقات الشبكة والامن الرقمي ولا غيرها افضل
    ع كل حال الله يعطيك العافية ويقويك
    السلام

  2. Posted الأحد 17 مايو 2009 at 10:48 ص | Permalink

    شكرا لك على هذه السلسلة الجميلة

    هل هناك أفضلية لاستخدام الرموز بدلا من السلاسل النصية؟

  3. Posted الأحد 17 مايو 2009 at 7:40 م | Permalink

    غالبا ما تستخدم الرموز بدلا من السلاسل النصية إذا كان الأمر المهم هو “الهوية” وليس “المحتوى”، وتكمن أفضلية الرموز في استخدامها الفعال للذاكرة: في كل مرة تستخدم فيها سلسلة نصية، يتم تخزين كائن جديد في مكان مختلف من الذاكرة، بينما الرموز التي تحمل الاسم نفسه تشير كلها إلى مكان واحد فقط في الذاكرة.

    لنجرب هذا المثال:

    puts "ruby".object_id # prints: 32563100
    puts "ruby".object_id # prints: 32559840
    puts :ruby.object_id  # prints: 111458
    puts :ruby.object_id  # prints: 111458

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

التعقيبات 2

  1. بواسطة روابـــ(7)ــط « Mutati0N UNITED STATES WordPress MU في الثلاثاء 12 مايو 2009 11:24 م

    [...] بكل ما يتعلق بسطح المكتب جنوم *WolframAlpha: هل ينافس جوجل؟ *تعلم أساسيات البرمجة بلغة روبي – بنى البيانات، بعض ا… *Demystifying Irb’s Commands * كيف أستخدم تويتر [...]

  2. [...] تعلم أساسيات البرمجة بلغة روبي – بنى البيانات، بعض الت… [...]

أضف تعليقاً

بريدك الالكتروني لن يعرض للآخرين. * حقول مطلوبة

*
*