Ответ 1
Ruby yield
не является итератором, как в С# и Python. yield
сам по себе действительно очень простая концепция, как только вы понимаете, как блоки работают в Ruby.
Да, блоки являются функциональной функцией программирования, хотя Ruby не является надлежащим образом функциональным языком. На самом деле Ruby использует метод lambda
для создания блочных объектов, который заимствован из синтаксиса Lisp для создания анонимных функций - вот какие блоки. С точки зрения компьютерных наук блоки Ruby (и Lisp лямбда-функции) заключаются в закрытиях. В Ruby методы обычно принимают только один блок. (Вы можете передать больше, но это неудобно.)
Ключевое слово yield
в Ruby - это просто способ вызова блока, который был передан методу. Эти два примера эквивалентны:
def with_log
output = yield # We're calling our block here with yield
puts "Returned value is #{output}"
end
def with_log(&stuff_to_do) # the & tells Ruby to convert into
# an object without calling lambda
output = stuff_to_do.call # We're explicitly calling the block here
puts "Returned value is #{output}"
end
В первом случае мы просто предполагаем наличие блока и говорим, чтобы его называть. В другом случае Ruby обертывает блок в объект и передает его в качестве аргумента. Первый - более эффективный и читаемый, но они практически одинаковы. Вы бы назвали одно из следующих:
with_log do
a = 5
other_num = gets.to_i
@my_var = a + other_num
end
И он напечатает значение, которое получило бы присвоение @my_var
. (ОК, так что это абсолютно глупая функция, но я думаю, что вы поняли эту идею.)
Блоки используются для многих вещей в Ruby. Почти в каждом месте, где вы бы использовали цикл на языке Java, он заменил в Ruby на методы, которые принимают блоки. Например,
[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value} # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]
Как отметил Андрей, он также обычно используется для открытия файлов и многих других мест. В принципе, в любое время, когда у вас есть стандартная функция, которая может использовать некоторую пользовательскую логику (например, сортировку массива или обработку файла), вы будете использовать блок. Есть и другие виды использования, но этот ответ уже так долго, я боюсь, это вызовет сердечные приступы у читателей с более слабыми конституциями. Надеюсь, это устранит путаницу в этой теме.