ブロックのキャプチャ¶
ブロックはキャプチャしてProc
に変換できます。Proc
は、関連付けられたコンテキスト(クロージャデータ)を持つコードブロックを表します。
ブロックをキャプチャするには、メソッドのブロックパラメータとして指定し、名前を付け、入力と出力の型を指定する必要があります。例えば
def int_to_int(&block : Int32 -> Int32)
block
end
proc = int_to_int { |x| x + 1 }
proc.call(1) # => 2
上記のコードは、int_to_int
に渡されたコードブロックをblock
変数にキャプチャし、メソッドから返します。proc
の型はProc(Int32, Int32)
で、単一のInt32
引数を受け取り、Int32
を返す関数です。
このようにして、ブロックはコールバックとして保存できます。
class Model
def on_save(&block)
@on_save_callback = block
end
def save
if callback = @on_save_callback
callback.call
end
end
end
model = Model.new
model.on_save { puts "Saved!" }
model.save # prints "Saved!"
上記の例では、&block
の型は指定されていません。これは、キャプチャされたブロックが引数を取らず、何も返さないことを意味します。
戻り値の型が指定されていない場合、proc呼び出しからは何も返されません。
def some_proc(&block : Int32 ->)
block
end
proc = some_proc { |x| x + 1 }
proc.call(1) # => nil
何かを返すには、戻り値の型を指定するか、アンダースコアを使用して任意の戻り値の型を許可します。
def some_proc(&block : Int32 -> _)
block
end
proc = some_proc { |x| x + 1 }
proc.call(1) # 2
proc = some_proc { |x| x.to_s }
proc.call(1) # "1"
break と next¶
return
とbreak
は、キャプチャされたブロック内では使用できません。next
は使用でき、ブロックを終了して値を返します。
with ... yield¶
キャプチャされたブロック内のデフォルトのレシーバは、with ... yield
を使用して変更できません。