Rubyでのブロックと歩留まり



Blocks Yields Ruby



解決:

はい、最初は少し不可解です。

Rubyでは、メソッドはコードの任意のセグメントを実行するためにコードブロックを受け取る場合があります。



メソッドがブロックを予期する場合、メソッドはを呼び出すことによってそれを呼び出します降伏関数。

これは、たとえば、リストを反復処理したり、カスタムアルゴリズムを提供したりする場合に非常に便利です。



次の例を見てください。

私は定義するつもりです名前で初期化された個人クラス、およびdo_with_nameメソッドは、呼び出されたときに、受信したブロックのname属性。

class Person def initialize(name)@name = name end def do_with_name yield(@name)end end

これにより、そのメソッドを呼び出して任意のコードブロックを渡すことができます。



たとえば、名前を出力するには、次のようにします。

person = Person.new( 'Oscar')#ブロックを渡すメソッドを呼び出すperson.do_with_name do | name | puts 'ねえ、彼の名前は#{name}' end

印刷します:

ねえ、彼の名前はオスカーです

ブロックは、パラメータとして、と呼ばれる変数を受け取ることに注意してください。名前(注:この変数は好きなように呼び出すことができますが、呼び出すのは理にかなっています名前)。コードが呼び出されたときこのパラメータを次の値で埋めます。@名前。

yield(@name)

別のアクションを実行するために別のブロックを提供できます。たとえば、名前を逆にします。

#名前を逆に保持する変数reversed_name = ''#別のブロックを渡すメソッドを呼び出しますperson.do_with_name do | name | reverse_name = name.reverse end puts reverse_name => 'racsO'

まったく同じ方法を使用しました(do_with_name)-それは単なる別のブロックです。

この例は簡単です。さらに興味深い使用法は、配列内のすべての要素をフィルタリングすることです。

days = ['monday'、 'tuesday'、 'wednesday'、 'thursday'、 'friday']# 't'で始まるものを選択しますdays.selectdo |アイテム| item.match / ^ t / end => ['火曜日'、 '木曜日']

または、たとえば文字列サイズに基づいて、カスタムの並べ替えアルゴリズムを提供することもできます。

days.sort do | x、y | x.size y.size end => ['月曜日'、 '金曜日'、 '火曜日'、 '木曜日'、 '水曜日']

これがあなたがそれをよりよく理解するのに役立つことを願っています。

ところで、ブロックがオプションの場合は、次のように呼び出す必要があります。

block_givenの場合はyield(value)?

オプションでない場合は、それを呼び出すだけです。

編集

@hmakは、これらの例のrepl.itを作成しました:https://repl.it/@makstaks/blocksandyieldsrubyexample


Rubyでは、メソッドは、通常の引数に加えてブロックが提供されるような方法で呼び出されたかどうかを確認できます。通常、これはを使用して行われますblock_given?メソッドですが、アンパサンド(&)最後の引数名の前。

メソッドがブロックで呼び出された場合、メソッドは次のことができます。必要に応じて、いくつかの引数を使用してブロックに制御を譲ります(ブロックを呼び出します)。次のことを示すこの例の方法を考えてみましょう。

def foo(x)puts'OK:called as foo(#{x.inspect}) 'yield(' A gift from foo! ')if block_given? end foo(10)#OK:foo(10)として呼び出されますfoo(123){| y | puts'BLOCK:#{y} How nice =) '} #OK:foo(123)として呼び出されます#BLOCK:fooからの贈り物です!なんて素敵な=)

または、特別なブロック引数構文を使用します。

def bar(x、&block)puts'OK:called as bar(#{x.inspect}) 'block.call(' A gift from bar! ')if block end bar(10)#OK:called as bar(10 )bar(123){| y | puts'BLOCK:#{y} How nice =) '} #OK:bar(123)と呼ばれる#BLOCK:バーからの贈り物!なんて素敵な=) 

誰かがここで本当に詳細な答えを提供する可能性は十分にありますが、Robert Sosinskiからのこの投稿は、ブロック、プロシージャ、ラムダ間の微妙な点についての優れた説明であることが常にわかりました。

私がリンクしている投稿はruby1.8に固有のものであると私は信じていることを付け加えておきます。 ruby 1.9では、ブロック変数がブロックに対してローカルであるなど、いくつかの変更が加えられています。 1.8では、次のようなものが得られます。

>> a = 'こんにちは' => 'こんにちは' >> 1.times a => 1 >> a => 'さようなら'

1.9はあなたに与えるでしょうが:

>> a = 'こんにちは' => 'こんにちは' >> 1.times a => 1 >> a => 'こんにちは'

このマシンには1.9がないので、上記でエラーが発生する可能性があります。