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:

    1. invoke(proc) # Error: wrong number of arguments for 'invoke' (1 for 0)

    You can actually pass a proc to a method that yields:

    1. def capture(&block)
    2. block
    3. end
    4. def twice
    5. yield
    6. yield
    7. end
    8. proc = capture { puts "Hello" }

    Or, combining the and -> syntaxes:

    1. twice &->{ puts "Hello" }

    Or:

    1. def say_hello
    2. puts "Hello"
    3. end
    4. 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:

    1. def foo
    2. yield 1
    3. end
    4. def wrap_foo(&block : Int32 -> _)
    5. puts "Before foo"
    6. puts "After foo"
    7. wrap_foo do |i|
    8. puts i
    9. end
    10. # Output:
    11. # Before foo
    12. # 1
    13. # 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:

    1. foo_forward do |i|
    2. end