When passing a block with args to another method (using &) the block does not accept the args anymore:
class Test
def bar(&block)
yield "Jim"
yield "John"
end
def foo(&block)
bar(&block)
end
end
t = Test.new
# works
t.bar do |name|
puts "Hi #{name}"
end
# does not work
t.foo do |name|
puts "Hi {name}"
end
I would expect both the #foo and the #bar call to output Hi Jim\nHi John\n, but this compile time error is raised instead:
Error in test.cr:17: wrong number of block arguments (given 1, expected 0)
t.foo do |name|
^~~
Tested on Crystal 0.20.0 [b0cc6f7] (2016-11-22) from tarball, Crystal 0.20.0+17 [d13e650] (2016-11-24) from source and play 0.19.4
You need to specify the type of the block in foo for this to work. For example:
def foo(&block : String ->)
bar(&block)
end
This is due to limitations in Crystal's type inference algorithm.
If you just want to forward a block, using bar { |name| yield name } instead of bar(&block) is highly recommended.
You can read more about this topic in the docs: https://crystal-lang.org/docs/syntax_and_semantics/block_forwarding.html
Yes, that works as expected for now. Maybe in the future we can improve this.
Most helpful comment
You need to specify the type of the block in
foofor this to work. For example:This is due to limitations in Crystal's type inference algorithm.
If you just want to forward a block, using
bar { |name| yield name }instead ofbar(&block)is highly recommended.You can read more about this topic in the docs: https://crystal-lang.org/docs/syntax_and_semantics/block_forwarding.html