2015-09-22 16 views
6

暗黙または明示的にブロックをいつコードするべきかを理解しようとしています。次のコードブロックを考える:暗黙的または明示的なコードブロックを使用する場合

  • 暗黙

    def two_times_implicit 
        return "No block" unless block_given? 
        yield 
        yield 
    end 
    
    puts two_times_implicit { print "Hello "} 
    puts two_times_implicit 
    
  • 明示

    def two_times_explicit (&i_am_a_block) 
        return "No block" if i_am_a_block.nil? 
        i_am_a_block.call 
        i_am_a_block.call 
    end 
    
    puts two_times_explicit { puts "Hello"} 
    puts two_times_explicit 
    

は、他の上で1つを使用してコードすることが望ましいですか?標準的なプラクティスはありますか?誰かが他よりもうまくやって動作するか、まったく動作しない場合がありますか?

+2

[documentation](http://ruby-doc.org/core-2.2.3/doc/syntax/methods_rdoc.html#label-Block+Argument)*によると、「あなたはそうでなければそれを操作したり、明示的なブロックパラメータなしでyieldを使用して別の方法に送信することは望ましくありません。 "* – Stefan

+0

それはたいてい個人的な趣味の好みです。ブロックを変数に格納するか、メソッドに渡す場合は、明示的な '&block'を使用する必要があります。それ以外の場合、ほとんどの人は暗黙的に(より速く)使用しますが、明快さのために明示的に好む場合があります(ほとんどの場合、パフォーマンスの違いはほとんどありません)。 – jrochkind

答えて

5

&経由でブロックを受信すると、ブロックから新しいprocオブジェクトが作成されるため、効率の観点からは使用しない方が良いでしょう。しかし、&を使用すると、一般に、ブロックを取るかどうかを決める方法が簡単になり、&を使うと、ブロックを引数とともに扱うこともできます。

+5

また、渡す場合は '&block'を使用する必要があります。 –

+0

"ブロックを取るかもしれないしないかもしれないメソッドを定義するのを簡単にする"と "引数と共にブロックを扱うこともできます" –

+0

引数を指定してブロックを処理する場合や、ブロックを使用する方法と使用しない方法を定義する場合は、明示的なバージョンは必要ありません。暗黙的に両方の場合に問題なく動作します。明示的に必要なのは、ブロックを変数に保存するか、別の方法に渡すかどうかだけです。 – jrochkind

4

実際には、very interesting readによれば、第2の変種は439%遅い(HackerNewsのrelated thread)。 &blockを通過する異なる実装されている間、インタプリタに専用C関数によって処理され、新しい環境を作成する大きなオーバーヘッドを有するyield介してブロックを作成し、通過するMRIで高度に最適化された一般的なケースであり、そして:DRは、

TLすべての呼び出しでそれ自身Procを作成します。

要約すると、それをさらに(たとえば次の関数に)渡す必要がある場合や、それ以外の方法で何らかの方法で操作する必要がある場合にのみ&blockを使用してください。それ以外の場合は、yieldを使用してください。

+0

@CarySwoveland、ありがとう、完了。 –

関連する問題