TL; DR if...end
は、ブロック
発現ないRubyで用語block
の適切な使用は、do...end
または中括弧{...}
間でメソッドに渡されたコードです。ブロックは、メソッド署名内で&block
構文を使用することによって、メソッド内でProc
に暗黙的に変換できます。この新しいProc
はProc
が暗黙的に作成されている、上記のコードで
def block_to_proc(&block)
prc = block
puts prc
prc.class
end
block_to_proc { 'inside the block' }
# "#<Proc:[email protected](irb):21>"
# => Proc
...繰り返し呼び出さ変数やデータ構造に格納されている他の方法、などに渡すことができ、独自のメソッドを持つオブジェクトでありますそのブロックを本体として変数block
に割り当てます。同様に、Proc
(またはlambda
、タイプはProc
)をブロックに「展開」して、引数リストの末尾に&block
の構文を使用することで、ブロックを予想しているメソッドに渡すことができます。
def proc_to_block
result = yield # only the return value of the block can be saved, not the block itself
puts result
result.class
end
block = Proc.new { 'inside the Proc' }
proc_to_block(&block)
# "inside the Proc"
# => String
ややblock
秒とProc
sの双方向のストリートのがありますが、それらは同じではありませんね。 Proc
を定義するには、block
をProc.new
に渡す必要があります。厳密に言えば、block
は、明示的に呼び出されるまで実行が延期されるメソッドに渡される単なるコードです。 Proc
はblock
で定義され、呼び出されるまでその実行も延期されますが、それは他のオブジェクトとまったく同じです。 block
はそれ自体では生き残ることができません。Proc
ができます。 if...else...end
、begin...rescue...end
、def...end
、class...end
、module...end
、until...end
:一方、block
又はblock of code
時々何気なくルビーで囲まれたコードのいずれか控えめチャンクを指すために使用される
はend
で終わるキーワード。しかし、これらは本質的にブロックではなく、実際にはそれらを表面上に似ています。彼らはしばしば、何らかの条件が満たされるまで実行を延期します。しかし、彼らは完全に独立して立つことができ、いつも戻り値を持っています。 Ruby-doc.orgの「表現」の使用はより正確です。プログラミング言語の表現は、プログラミング言語解釈する一つまたは 以上の明示的な値、定数、変数、演算子、および関数 の組み合わせであるwikipedia
から
(その特定 規則に従って優先度と関連性)を計算し、別の値を生成するように計算します(ステートフルな環境では " に戻ります")。
あなたはこの
return_value = if 'expression'
true
end
return_value # => true
のようなものがブロック
return_value = do
true
end
# SyntaxError: (irb):24: syntax error, unexpected keyword_do_block
# return_value = do
# ^
でブロックが独自に表現ではないことをやってみ行うことができます理由です。生き残るためには、yield
またはProc
への変換が必要です。ブロックを必要としないメソッドにブロックを渡すとどうなりますか?
ブロックは完全に失われています。戻り値がなく、実行されず、まったく存在しないかのようにブロックが消えます。式を完成させて戻り値を生成するには、yield
が必要です。
class Object
def puts(*args)
super
yield if block_given?
end
end
puts("mindful") { "of blocks" }
# "mindful"
# => "of blocks"