سؤال

لقد بدأت تعلم روبي, ولقد قرأت بضعة دروس و حتى اشتريت كتاب ("البرمجة روبي 1.9 - عملي للمبرمجين دليل"), و لقد وجدت شيئا جديدا لم أره من قبل في أي من اللغات الأخرى أعرف (أنا أعمل PHP webdeveloper).

كتل & Procs.أعتقد أنني أفهم ما هي عليه ، ولكن ما لا أفهمه هو لماذا هم عظيم جدا, و متى و لماذا يجب استخدامها.في كل مكان أنظر يقولون كتل procs هي ميزة كبيرة في روبي ، ولكن لا فهم لهم.

هل من أحد هنا تعطي مجموع روبي-مبتدئ مثلي بعض تفسيرات ؟

هل كانت مفيدة؟

المحلول

هناك الكثير من الأشياء التي هي جيدة عن كتل.المصعد الملعب:كتل اسمحوا لنا بالمرور حول الإجراءات بنفس الطريقة نحن عادة تمر في جميع أنحاء البيانات.

المستوى الأكثر وضوحا هو أنها تتيح لك أشياء مجردة إلى الوظائف التي لن يكون من الممكن خلاف ذلك.على سبيل المثال, دعونا ننظر إلى حالة شائعة حيث لديك قائمة من الأشياء التي تريد تصفية فقط تشمل العناصر التي تطابق بعض المعيار:

int list[50] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50};
int evenNumbers[50] = {0};
int copyIndex = 0;
for (int i = 0; i < 50; i++) {
    if (list[i] % 2 == 0) {
        evenNumbers[copyIndex++] = list[i];
    }
}

هنا هو كيف يمكنك كتابة ذلك في روبي:

list = 1..50
listCopy = list.select {|n| n.even?}

كل مشترك busywork تم نقل التعليمات البرمجية الخاصة بك إلى طريقة ذات معنى الاسم.نحن لا نهتم نسخ مجموعة والذهاب من خلال الفهارس و كل ما نريد قائمة تمت تصفيتها.و هذا ما select يعطينا.كتلة يسمح لنا بالمرور عادتنا المنطق في هذه الطريقة القياسية.

ولكن التكرار ليست المكان الوحيد حيث هذا "ثقب في الوسط نمط" هو مفيد.على سبيل المثال, إذا كنت تمر كتلة File.open, ، فإنه سيتم فتح ملف تنفيذ كتلة مع الملف ثم قم بإغلاق الملف لك.

شيء آخر أن كتل تعطينا هي قوية حقا شكل رد.على سبيل المثال, بدون كتل, علينا أن نفعل شيئا مثل هذا (على أساس مدى الحوارات فعلا العمل في الهدف-C الكاكاو):

class Controller
  def delete_button_clicked(item)
    item.add_red_highlight
    context = {:item => item}
    dialog = Dialog.new("Are you sure you want to delete #{item}?")
    dialog.ok_callback = :delete_OK
    dialog.ok_receiver = self
    dialog.cancel_callback = :cancel_delete
    dialog.cancel_receiver = self
    dialog.context = context
    dialog.ask_for_confirmation
  end

  def delete_OK(sender)
    delete(sender.context[:item])
    sender.dismiss
  end

  def cancel_delete(sender)
    sender.context[:item].remove_red_highlight
    sender.dismiss
  end
end

تعرض ما لديها.مع كتل يمكن أن نقوم بذلك بدلا من ذلك (على أساس النمط الشائع استخدامها في العديد من روبي المكتبات):

class Controller
  def delete_button_clicked(item)
    item.add_red_highlight
    Dialog.ask_for_confirmation("Are you sure you want to delete #{item}?") do |response|
      response.ok { delete item }
      response.cancel { item.remove_red_highlight }
    end
  end
end

هذا هو في الواقع اثنين من مستويات من كتل ـ do...end كتلة اثنين {}على غرار كتل.ولكن من يقرأ طبيعي جدا, أليس كذلك ؟ يعمل هذا لأن كتلة يلتقط السياق أنه خلق لذلك لا تحتاج إلى تمرير جميع أنحاء self و item.

أما بالنسبة Procs ، انهم مجرد كائن المجمع كتل.ليس كثيرا جدا لهم.

نصائح أخرى

من المهم أن عرض القطع ليس باستخدام طرق للبدء في كتلة التعليمات البرمجية ، كنت تأخذ في الواقع كتلة واستخدامه مثل معلمة في وظيفة.

حتى عند استخدام كل طريقة تكرار عبر مجموعة مثل ذلك:

superOverFlowArray.each { |flow| puts flow }

تقوم بإرسال كتلة {التدفق || يضع تدفق } في كل طريقة.رمز تقول روبي إرسال القيمة الحالية مجموعة إلى هذه الكتلة في مكان التدفق||.

Procs تأخذ كتلة وجعلها في متغير.Procs هي كائن الحالات التي تحمل كتل.كتل مرت كمعلمة إلى proc و يتم تنفيذها عند استدعاء استدعاء الأسلوب على أن بروك سبيل المثال.

حتى هنا هو بروك سبيل المثال:

def category_and_title(category)
     Proc.new { |title| "The title is: " + title + " in category: " + category }
end

myFirstTitle = category_and_title("Police Drama")
mySecondTitle = category_and_title("Comedy")

puts myFirstTitle.call("Law and Order")
puts mySecondTitle.call("Seinfeld")
puts myFirstTitle.call("CSI")

بروك سوف تذكر الأصلي الفئة التي تم تمريرها في ، مما يتيح وسيلة مريحة تجمع أنواع.

وتستخدم كتل من العديد من الأساليب في روبي الطبقات ، فهي تستخدم فيها في PHP يمكنك استخدام رد الاتصال.

[1,2,3,4,5].each {|i| print "#{i} "}

[1,2,3,4,5].each do |i|
  print "#{i} "
end

File.open('p014constructs.rb', 'r') do |f1|  
  while line = f1.gets  
    puts line
  end
end

PHP5 قدم مجهول المهام ؛ بدلا من استخدام الاستدعاء ، يمكنك استخدام وظيفة مجهول.

echo preg_replace_callback('~-([a-z])~', function ($match) {
  return strtoupper($match[1]);
}, 'hello-world');

Procs, المعروف أيضا باسم الإغلاق أو lambdas هو مفهوم في روبي التي قد تبدو مربكة في البداية خاصة إلى مبتدئ.باختصار ، procs تسمح لك لتمرير قانون الكتل مع سهولة.مثال أدناه

    hello = Proc.new do |x, y|
      puts "i am a proc"
      sum = x+y
      puts "sum: #{sum}"
    end

الآن للاستفادة من هذا كتلة من التعليمات البرمجية فقط استدعاء الأسلوب "الدعوة" على مرحبا.نلاحظ أن المثال أعلاه يتلقى الحجج x و y التي كتلة التعليمات البرمجية يستخدم.لذلك تأكد من أن تمر في الحجج عند استدعاء من بروك كائن مثل فعلت أدناه:

    hello.call(2, 3)

مما أسفر عن النتائج التالية:

    i am a proc
    sum: 5

يا هلا!!هذا هو وسيلة سهلة لإنشاء مجلد الكائن.كيف مفيدة هو هذا ؟ حسنا, proc الكائنات تسمح لك لتمرير حول أجزاء من التعليمات البرمجية.الرسم التوضيحي أدناه يوضح ذلك بشكل أفضل من خلال الاستفادة من بروك بإنشائه في المثال أعلاه.دعونا خلق عشوائي الصف ،

    class SomeClass
      def initialize(&block)
        @block = block
      end

      def output_value(x, y)
        @block.call(x, y)
      end
    end

الآن, دعونا إنشاء مثيل SomeClass,

    some_class = SomeClass.new(&hello)

علما بأن العطف علامة "&" قبل مرحبا يسمح لك لتمرير proc كائن كحجة.

وأخيرا دعونا إخراج القيمة عن طريق تمرير 2 الحجج ، مثل أدناه:

    some_class.output_value(1, 3)

النتيجة التي تحصل هي على النحو التالي:

    i am a proc
    sum: 4

انظر!!الامر بهذه البساطة.كنت قادرا على تمرير قطعة من التعليمات البرمجية في جميع أنحاء.Procs مفيدة جدا أن روبي يجعل استخدام من ذلك كثيرا.نأمل أن يكون هذا السوبر مفيدة :)

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

كتل procs تمكنك من استخراج قطع صغيرة من التعليمات البرمجية دون الحمل الكامل و تعقيد أساليب.

حتى map في حد ذاته هو قوي جدا و مسج بنيت حول هذا المفهوم نفسه:

  ['spite','rest','purpose'].map {|s| s << 'ful' }

و يمكنك رمي المنطق في إذا لزم الأمر

  ['sprite','restful','luck'].map {|s| s << (s.end_with?('uck') ? 'i' : '') << 'ly' }

هناك ذكية المشغل '&' الذي يعني "تحويل الرمز إلى مجلد و نسميه" ، حتى تتمكن من تحويل الأجسام السلاسل:

  ['spite',12,:purpose].map(&:to_s)

واستخدام الإغلاق و بين الكتابة بسيط الإغلاق يمكن أن نجد أين المجاورة من الأرقام تظهر.هذا هو الخرقاء بدلا روبي, ولكن أكثر إيجازا من معظم اللغات:

  last = -2 # this variable is accessed and changed within the closure
  objs.sort.map do |o|
    if (last + 1) != o
       last = o
       nil # not one more than previous so return nil
    else
       o
    end
  end.compact  # compact removes nils

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top