Рубин: Урожай в перечисляемом - PullRequest
5 голосов
/ 30 июля 2011

Я хотел бы быть в состоянии получить в перечисляемом блоке, чтобы создать некоторый шаблонный эталонный код.

В основном я хотел бы сделать что-то такое (упрощенно):

def iterator( enumerable, &block )
  iterations = enumerable.size
  counter = 0
  enumerable.each do |item|
    counter +=1
    puts "Iterating #{counter}/#{iterations}..."
    yield
  end
end

Тогда я хотел бы иметь возможность использовать этот метод для того, чтобы обернуть этот шаблонный эталонный код вокруг блока, который я буду перебирать, чтобы я мог вызвать что-то вроде:

# assuming foo is an enumerable collection of objects
iterator foo do
  item.slow_method
  item.mundane_method
  item.save
end

... и когда этот код будет выполнен, я получу следующий вывод журнала:

Iterating 1/1234...
Iterating 2/1234...
Iterating 3/1234...

Кажется, что такого рода вещи должны быть возможны, но я не смог выяснить ни синтаксис, ни то, что такое называется (для того, чтобы найти его).

Проблема в том, что мне нужно обернуть шаблон как ВНЕ перечисляемого объекта, который будет повторяться, так и ВНУТРИ блока итерации. Я могу передать перечислимый объект просто отлично, но я не могу вызывать методы для итерированных объектов из блока, который я передаю.

Надеюсь, это объяснение имеет смысл, мне трудно его описать. Пожалуйста, оставляйте комментарии, если вам нужно что-то разъяснить, я постараюсь объяснить лучше.

1 Ответ

7 голосов
/ 30 июля 2011

Оператор Ruby yield может принимать аргументы. Вы хотели бы сказать

yield item

Это передает «текущий» элемент вашему «внешнему» блоку.

Надеюсь, я правильно понял вопрос.

ДОПОЛНЕНИЕ

А вот код, чтобы показать его в действии:

class Item
  def initialize(id)
    @id = id
  end
  def slow_method()
    puts "slow #@id"
  end
  def mundane_method()
    puts "mundane #@id"
  end
  def save()
    puts "save #@id"
  end
end

foo = [Item.new(100), Item.new(200), Item.new(300)]

def iterator(enumerable, &block)
  iterations = enumerable.size
  counter = 0
  enumerable.each do |item|
    counter +=1
    puts "Iterating #{counter}/#{iterations}..."
    yield item
  end
end

iterator foo do |item|
  item.slow_method
  item.mundane_method
  item.save
end
...