19

現在、David A.Blackの「TheWell-GroundedRubyist」を読んでいて、10.9章(列挙子と列挙可能性の次の次元)に固執しました。私の質問はyield方法についてです。yieldRubyの文脈での単語の意味は何ですか?私の母国語はロシア語です、そしてグーグル翻訳は私を混乱させているたくさんの翻訳の変形を私に示します。それらのいくつかがあります:与える持ってくる降伏するあきらめる)、作り出す同意する従う、そして他の多く。

UPD:Enumerator :: Yielder#yieldメソッドの意味を理解しようとしているが、yieldキーワード自体は理解しようとしていないという事実に注意してください 。

UPD_2:列挙子に関する興味深い記事「Rubyのレイジー列挙子」を見つけました。

4

6 に答える 6

23

Rubyのコンテキストでは、 yieldという単語は実際には特別な意味を持ちません。これは、他のすべてのプログラミング言語、またはプログラミングやコンピュータサイエンス全般で意味するのと同じことを意味します。

これは通常、ある種の実行コンテキストが制御フローを別の実行コンテキストに引き渡すときに使用されます。たとえば、Unixにはsched_yield、スレッドがCPUを別のスレッド(またはプロセス)に譲るために使用できる関数があります。コルーチンでは、この用語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、再度呼び出されるまで制御を放棄するため、フィボナッチ数が1つずつ生成され、基本的にすべてのフィボナッチ数の無限に長いリストが生成されます。

Fiber.yield同様の目的を果たす別の方法があります。Fiber(実際、コルーチンの単なるRubyの名前であるため、上記ですでに説明しました。)の内部で、元々制御を与えていた実行コンテキストに制御を戻すためにFiber呼び出します。Fiber.yield

最後にyield、メソッド本体内で使用されるキーワードがあります。これは、メソッドに渡されたブロックへの制御を放棄するために使用されます。

少なくともこの場合(つまり最初の例)では、を呼び出すたびに新しい値が生成されるため、を生成するEnumeratorとさらに解釈できることに注意してください。yieldEnumeratoryield

于 2011-02-21T20:16:48.550 に答える
3

列挙子での譲歩の文脈では、その意味は「もたらす」に最も近いものです。列挙子は、yielderオブジェクトの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!" }
于 2011-02-21T19:22:27.047 に答える
3

プログラミングRuby1.9がyieldキーワードについて何と言っているかを読むのは面白いかもしれません。

プログラミング言語愛好家は、キーワードがLiskovの言語CLUのyield関数をエコーするために選択されたことを知って喜ぶでしょう。このyield言語は、30年以上前のものでありながら、CLUレスによってまだ広く利用されていない機能が含まれています。 。

もっと読む:

CLUの歴史(pdf)

バーバラ・リスコフ(ウィキペディア)

于 2011-02-21T22:41:00.850 に答える
2

@ Prostosuper、私が一番好きな関連する定義はこれです:

譲歩、譲歩、付与(譲歩、他人の身体的支配に委ねる、または放棄する)

@Jamie Forrestの例では、wage_warが呼び出されたときに、「どうすればよいですか?」が最初に出力され、次にフロー制御がwage_warが呼び出されたブロックに渡され(譲歩、譲歩、付与、譲渡)、結果として「Surrender!」になります。印刷されています。そのブロックが完了すると、wage_warでフロー制御が再開されます。イールドの後に別のステートメントがある場合、「Surrender!」の後にwage_warでフロー制御が再開されたときに実行されます。印刷されました。

編集:@Prostosuperは、ブロックではなく列挙子に関係するため、yieldについて質問しました。私の例では、ブロックでの使用について説明しています。Enumerator :: Yielder#yieldに関するSOの質問(回答付き)はこちらです。定義の意味はまだ適用されます。

于 2011-02-21T19:39:26.243 に答える
0

ルビーのコンテキストでは、yieldは、メソッドにパラメーターとして渡されたブロックを「もたらします」:)。

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

my_methodがyieldに達すると、コードp"helloworld"が実行されます。

于 2011-02-21T18:20:22.147 に答える
0

C#では、ループ内のyieldはreturnキーワードのようなものであり、リストを反復するループの一部です。では、なぜリターンを使わないのですか?なぜなら、yieldを使用すると、そのリストの値を繰り返しながら、ループに制御を戻すことができるからです。つまり、歩留まりは制御メカニズムのようなものかもしれません。

于 2020-09-27T08:34:25.960 に答える