Block argument usage affects lambda semantic
The following snippet demonstrate the issue:
def pass_after_use(&block) raise unless block lambda(&block).call end def direct_pass(&block) lambda(&block).call end pass_after_use do |_arg| puts "fine, because block is materialized into a Proc before it is passed to #lambda" end direct_pass do |_arg| puts "Raises because all args are required. This is not printed" end
fine, because block is materialized into a Proc before it is passed to #lambda Traceback (most recent call last): 2: from lambda-block-pass.rb:14:in `<main>' 1: from lambda-block-pass.rb:7:in `direct_pass' lambda-block-pass.rb:14:in `block in <main>': wrong number of arguments (given 0, expected 1) (ArgumentError)
I think having the line
raise unless block affect
Kenrel#lambda's semantic is pretty surprising. Note that if I do
raise unless block_given?, call to the lambda without arg also raises.
If I was to decide, I would always have the resulting lambda have required arguments even after multiple levels of block pass. That is, as long as the original block is a literal block.
This is either a breaking change or a regression from 2.4. The same script executes without raising in 2.4.5 (block arguments are always materialized).