Issue #15620 has been updated by Eregon (Benoit Daloze).


Right, `define_method` is kind of an exception.
However, it doesn't mutate the lambda-ness of the Proc, it creates a new Proc from that block with lambda semantics.

It's still confusing for the user though, as a given literal block could be used as both Proc and lambda, which is likely unexpected (e.g. break/return will cannot work correctly in that block).
This can also be achieved with `send(:proc or :lambda) { ... }`.

----------------------------------------
Bug #15620: Block argument usage affects lambda semantic
https://bugs.ruby-lang.org/issues/15620#change-76982

* Author: alanwu (Alan Wu)
* Status: Open
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
* Target version: 
* ruby -v: 
* Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
The following snippet demonstrate the issue:

``` ruby
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

```

Output:
```
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).





-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>