Block forwarding
In the above example, invoke
receives a block. We can’t pass proc
directly to it because invoke
doesn’t receive regular arguments, just a block argument. We use &
to specify that we really want to pass proc
as the block argument. Otherwise:
invoke(proc) # Error: wrong number of arguments for 'invoke' (1 for 0)
You can actually pass a proc to a method that yields:
def capture(&block)
block
end
def twice
yield
yield
end
proc = capture { puts "Hello" }
Or, combining the and ->
syntaxes:
twice &->{ puts "Hello" }
Or:
def say_hello
puts "Hello"
end
twice &->say_hello
You can also use the &block
syntax to forward blocks, but then you have to at least specify the input types, and the generated code will involve closures and will be slower:
def foo
yield 1
end
def wrap_foo(&block : Int32 -> _)
puts "Before foo"
puts "After foo"
wrap_foo do |i|
puts i
end
# Output:
# Before foo
# 1
# After foo
Try to avoid forwarding blocks like this if doing yield
is enough. There’s also the issue that break
and next
are not allowed inside captured blocks, so the following won’t work when using &block
forwarding:
foo_forward do |i|
end