Почти идентично. Хотя семантика yield
Python и Ruby несколько различается, в данном случае они почти полностью совпадают.
Ruby 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
(это то, что рубисты предпочитают for
):
numbers_and_doubles(5).each do |num, double|
puts "#{num} * 2 = #{double}"
end
Но, как я уже сказал, несмотря на то, что они делают что-то немного другое, исходный Ruby выше (с yield
) удивительно похож на исходный Python выше (с yield
). Их употребление немного отличается, но соответствует идиоме каждого языка.
В вашем случае, если вы оставите yield
точно так же, как в вашем Python, строка, которая его потребляет, изменится с 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), но я хотел иметь для сравнения код, похожий на оба языка.
person
Amadan
schedule
29.03.2019