الصنف Enumerator في روبي

من موسوعة حسوب


الصنف Enumerator هو صنفٌ يسمح بتنفيذ عملية التكرار الداخلي والخارجي على الكائنات. يمكن إنشاء كائنات من هذا الصنف باستعمال إحدى التوابع التالية: Kernel.to_enum، أو Kernel.enum_for، أو new.

أغلب التوابع في هذا الصنف تملك شكلين هما: الشكل الكتلي (block form) الذي تقيَّم فيه المحتويات لكل عنصر في المجموعة التعدادية، والشكل الغير كتلي (non-block form) الذي يعيد كائنًا جديدًا من النوع Enumerator يغلِّف التكرار.

enumerator = %w(one two three).each
puts enumerator.class # => Enumerator

enumerator.each_with_object("foo") do |item, obj|
  puts "#{obj}: #{item}"
end

# foo: one
# foo: two
# foo: three

enum_with_obj = enumerator.each_with_object("foo")
puts enum_with_obj.class # => Enumerator

enum_with_obj.each do |item, obj|
  puts "#{obj}: #{item}"
end

# foo: one
# foo: two
# foo: three

هذا يسمح لك بربط الكائنات Enumerator مع بعضها بعضًا. على سبيل المثال، يمكنك تحويل كل عنصر من عناصر قائمة إلى سلسلة نصية تحوي الفهرس والعنصر بالشكل التالي:

puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
# => ["0:foo", "1:bar", "2:baz"]

يمكن أيضًا استعمال الصنف Enumerator كمكرِّر داخلي. على سبيل المثال، يعيد التابع next القيمة التالية للمكرِّر أو يطلق الاستثناء StopIteration إن وصل الكائن Enumerator إلى النهاية.

e = [1,2,3].each   # returns an enumerator object.
puts e.next   # => 1
puts e.next   # => 2
puts e.next   # => 3
puts e.next   # raises StopIteration

يمكنك استعمال هذا المثال لتنفيذ تكرار داخلي بالشكل التالي:

def ext_each(e)
  while true
    begin
      vs = e.next_values
    rescue StopIteration
      return $!.result
    end
    y = yield(*vs)
    e.feed y
  end
end

o = Object.new

def o.each
  puts yield
  puts yield(1)
  puts yield(1, 2)
  3
end

# use o.each as an internal iterator directly.
puts o.each {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3

# convert o.each to an external iterator for
# implementing an internal iterator.
puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3

توابع الصنف العامة

new

ينشئ كائنًا جديدًا من النوع Enumerator يمكن استعماله ككائن قابل للتعداد (Enumerable).

توابع النسخة العامة

each

يتكرر عبر الكتلة المعطاة وفقًا للكائن المُعدِّد الذي استدعي معه والطريقة التي أُنشِئ بها.

each_with_index

يشبه التابع with_index باستثناء أنه لا يوجد إزاحة بادئة لبدء العملية عند قيمة محدَّدة.

each_with_object

يكرر الكتلة المعطاة على كل عنصر من عناصر الكائن الذي استدعي معه مع كائن آخر اعتباطي (الكائن المُمرَّر إليه).

feed

يضبط القيمة المراد إعادتها عبر الاستدعاء yield التالي داخل e.

inspect

ينشئ نسخةً قابلةً للطباعة من e.

next

يعيد الكائن التالي في المُعدِّد الذي استدعي معه، ويحرك موضع المؤشر الداخلي للأمام خطوة واحدة.

next_values

يعيد مصفوفة تحوي الكائن التالي في المُعدِّد الذي استدعي معه، ويحرك موضع المؤشر الداخلي للأمام خطوةً واحدةً.

peek

يعيد الكائن التالي في المُعدِّد الذي استدعي معه ولكن لا يحرِّك موضع المؤشر الداخلي للأمام. 

peek_values

يعيد مصفوفة تحوي القيمة التالية في المُعدِّد الذي استدعي معه بشكل مشابه للتابع next_values ولكن لا يحرِّك موضع المؤشر الداخلي للأمام.

rewind

يعيد موضع مؤشر السلسلة التعدادية (enumeration sequence) إلى البداية.

size

يعيد حجم المُعدِّد الذي استدعي معه، أو يعيد القيمة nil إن لم يكن بالإمكان حساب الحجم بالنمط الكسول (lazily).

with_index

يكرر الكتلة المعطاة على كل عنصر من عناصر المُعدِّد الذي استدعي معه مع فهارسها والتي تبدأ عند موضع محدَّد.

with_object

يكرر الكتلة المعطاة على كل عنصر من عناصر المُعدِّد الذي استدعي معه مع كائن اعتباطي (الكائن المُمرَّر إليه) ثم يعيد هذا الكائن.

مصادر