Значение слова yield - PullRequest
       36

Значение слова yield

13 голосов
/ 21 февраля 2011

В настоящее время я читаю "Обоснованный Рубиист" Дэвида А. Блэка, и я застрял в 10.9 главе (Перечислители и следующее измерение перечислимости).У меня вопрос по поводу yield метода.Что означает слово yield в контексте Ruby?Мой родной язык русский, и Google Translate показывает мне несколько вариантов перевода, которые меня смущают.Вот некоторые из них: дать , принести , сдаться ( сдаться ), произвести , согласен , соответствует и многим другим.

UPD: пожалуйста, обратите внимание на тот факт, что я пытаюсь понять смысл слова Enumerator :: Yielder # yield метод, но не само ключевое слово yield.

UPD_2: Я нашел интересную статью о перечислителях: " LazyСчетчики в Ruby".

Ответы [ 5 ]

19 голосов
/ 21 февраля 2011

Слово yield на самом деле не имеет никакого особого значения в контексте Ruby. Это означает то же самое, что и в любом другом языке программирования, или в программировании и информатике в целом.

Обычно используется, когда какой-то контекст выполнения передает поток управления в другой контекст выполнения. Например, в Unix есть функция sched_yield, которую поток может использовать для передачи ЦП другому потоку (или процессу). В сопрограммах термин yield обычно используется для передачи управления от одной сопрограммы к другой. В C # есть ключевое слово yield, которое используется методом итератора для передачи управления методу итерации .

И на самом деле это последнее использование в точности совпадает с использованием метода Enumerator::Yielder#yield в Ruby, о котором вы спрашивали. Вызов этого метода приостановит перечислитель и передаст управление перечисляющему методу.

Пример:

fibs = Enumerator.new do |y|
  a, b = 0, 1
  y.yield a
  loop do
    y.yield b
    a, b = b, a + b
  end
end

puts fibs.next #  0
puts fibs.next #  1
puts fibs.next #  1
puts fibs.next #  2
puts fibs.next #  3
puts fibs.next #  5
puts fibs.next #  8
puts fibs.next # 13
puts fibs.next # 21

Как видите, существует бесконечный цикл. Очевидно, что если бы этот цикл работал сам по себе, он не принес бы особой пользы. Но поскольку каждый раз, когда он попадает в метод yield, он отказывается от управления, пока не будет вызван снова, это будет генерировать числа Фибоначчи одно за другим, по существу представляя бесконечно длинный список всех чисел Фибоначчи.

Существует еще один метод, Fiber.yield, который служит аналогичной цели. (На самом деле, я уже описал это выше, потому что Fiber - это просто имя Ruby для сопрограмм.) Внутри Fiber вы вызываете Fiber.yield, чтобы вернуть управление контексту выполнения, который изначально предоставлял вам управление.

Наконец, есть ключевое слово yield, которое используется внутри тела метода, чтобы передать управление блоку, который был передан в метод.

Обратите внимание, что, по крайней мере, в случае Enumerator (т.е. в первом примере) вы можете дополнительно интерпретировать yield как для получения , поскольку Enumerator каждый раз выдает новое значение он звонит yield.

3 голосов
/ 21 февраля 2011

В контексте уступки в Перечислителе значение наиболее близко к «породить». Перечислитель вызывает метод yield своего объекта-получателя, который «выводит» любое переданное ему значение.

give_me = Enumerator.new do |yielder|
  (1..5).each do |n|
    yielder.yield n
  end
end

5.times do
  p give_me.next
end

В результате:
1
2
3
4
5

В случае уступки блоку значение наиболее близко к «сдаче». Метод с оператором yield передает исполнение любому блоку, который вы передали этому методу.

def wage_war
  p "What should I do?"
  yield
end

wage_war { p "Surrender!" }
2 голосов
/ 22 февраля 2011

Вам может показаться забавным прочитать, что программирование Ruby 1.9 говорит о ключевом слове yield:

Любители языка программирования будут рады узнать, что ключевое слово yield было выбрано, чтобы повторить результат функционируют на языке CLU Лискова, языке, которому более тридцати лет, но который содержит не были широко использованы без CLU.

Больше чтения:

История CLU (pdf)

Барбара Лисков (Википедия)

2 голосов
/ 21 февраля 2011

@ Prostosuper, родственное определение, которое мне нравится больше всего, это это :

уступать, уступать, предоставлять (уступать; сдаваться или отказываться от физического контроля другого)

В примере @Jamie Forrest, когда вызывается wage_war, "Что мне делать?"сначала печатается, затем управление потоком дает (уступлено, передано, предоставлено, передано) блоку, с которым был вызван wage_war, что приводит к "Surrender!"печатается.После завершения этого блока управление потоком возобновляется в wage_war.Если бы после оператора был другой оператор, он был бы выполнен, когда управление потоком возобновилось в wage_war после "Surrender!"был напечатан.

РЕДАКТИРОВАТЬ : @Prostosuper спросил о доходности, поскольку она относится к Перечислители , а не блоков, и мой пример обсуждает его использование вблоки.SO вопрос (с ответами) о Enumerator :: Yielder # yield равен здесь .Смысл определения остается в силе.

0 голосов
/ 21 февраля 2011

yield, в контексте ruby ​​"приносит" :) блок, переданный в качестве параметра в ваш метод.

def my_method
    p "I have to say something:"
    yield
end

my_method do
   p "hello world!"
end

печатает

I have to say something:
hello world

код p "hello world"выполняется, когда my_method достигает доходности

...