В случае итераторов, думайте о них как об интерфейсе в Java: вы можете сделать цикл for в Ruby, но все объекты, которые вы можете захотеть перебрать (должны), реализуют метод 'each', который принимает блок (т.е. закрытие, анонимная функция).
Блоки используются повсеместно в Ruby. Представьте, что у вас есть этот массив:
[1, 2, 3, 4, 5, 6].each do |i| puts i.to_s end
Здесь вы создаете массив, а затем вызываете метод 'each' для него. Вы передаете блок ему. Вы можете выделить это следующим образом:
arr = [1, 2, 3, 4, 5, 6]
string_printer = lambda do |i| puts i.to_s end
arr.each(&string_printer)
Интерфейс такого типа реализован в других вещах: коллекция Hash позволяет перебирать пары ключ-значение:
{:name => "Tom", :gender => :male}.each do |key, value| puts key end
do..end можно заменить фигурными скобками, например:
[1, 2, 3, 4, 5, 6].each {|i| puts i.to_s }
Этот тип итерации стал возможен благодаря функциональному программированию, которое использует Ruby: если вы создаете класс, которому нужно что-то итерировать, вы также можете реализовать каждый метод. Рассмотрим:
class AddressBook
attr_accessor :addresses
def each(&block)
@addresses.each {|i| yield i }
end
end
Все виды классов реализуют интересную функциональность с помощью этого шаблона блока: посмотрите, например, метод String each_line и each_byte.