Почти идентично.Хотя семантика Python и Ruby yield
несколько отличается, в этом случае они почти точно совпадают.
Ruby's yield
вызывает блок, который передается в функцию, давая ей свои параметры.
Python yield
делает функцию генератором и генерирует один выход из нее.
Оба они имеют смысл только в контексте функции, так что только ваш цикл while
слишкомкраткий контекст, чтобы использовать его.Но давайте возьмем что-то вроде этого в качестве упрощенного примера в Ruby:
def numbers_and_doubles(n)
i = 0
while i < n
yield i, 2 * i
i += 1
end
end
Эта функция принимает блок с одним параметром, затем генерирует числа до этого числа вместе с их двойными и выполняет этот блок с этими параметрами:
numbers_and_doubles(5) do |num, double|
puts "#{num} * 2 = #{double}"
end
Поскольку блоки в основном совпадают с функциями обратного вызова, это эквивалентно этому Python:
def numbers_and_doubles(n, callback):
i = 0
while i < n:
callback(i, i*2)
i += 1
def output(num, double):
print(f"{num} * 2 = {double}")
numbers_and_doubles(5, output)
С другой стороны, Python yield
создаетгенератор - функция, которая возвращает функцию, которая может производить значения по требованию:
def numbers_and_doubles(n):
i = 0
while i < n:
yield i, 2 * i
i += 1
Наиболее естественный способ использования генератора - через цикл for
:
for num, double in numbers_and_doubles(5):
print(f"{num} * 2 = {double}")
В Ruby наиболее близким буквальным переводом является Enumerator
:
def numbers_and_doubles(n)
Enumerator.new do |yielder|
i = 0
while i < n
yielder.yield(i, i*2)
i += 1
end
end
end
, а наиболее естественный способ потребления Enumerator
- это each
(именно это Rubyists предпочитает for
):
numbers_and_doubles(5).each do |num, double|
puts "#{num} * 2 = #{double}"
end
Но, как я уже сказал, хотя они и делают что-то немного другое, оригинальный Ruby выше (с yield
) удивительно похож на оригинальный Python выше (с yield
).То, как они используются, немного отличается, но соответствует идиоме каждого языка.
В вашем случае, если вы оставите yield
точно так же, как в вашем Python, строка, которая его потребляет, изменится с * 1046 в Ruby*
backtrack do |prev_x, prev_y, x, y|
до Python
for prev_x, prev_y, x, y in backtrack():
Вы можете узнать больше на Выход Python против выхода Ruby .
Обратите внимание, что наиболее естественный способнаписать этот цикл не while
ни на одном языке (я бы использовал range
в Python и times
в Ruby), но я хотел иметь код, который выглядит одинаково для обоих языков, для сравнения.