Issue #16260 has been updated by zverok (Victor Shepelev).


> As a symbol proc cannot know the method to be invoked, so now I think it cannot be lambda.
> In the case `:+`, it looks like a lambda, but it is **not always true.**

@nobu, I am not sure I get it right. Can you please show when it is not true?..
For as far as I can understand, there are two distinctions of lambda:
1. Its `return` returns from lambda itself, not enclosing scope
2. It treats parameters strictly, without implicit unpacking/optionality

Now, `:+.to_proc` behaves this way:
```ruby
PLUS = :+.to_proc
PLUS.call(1, 2)
# => 3 
PLUS.call([1, 2])
# ArgumentError (wrong number of arguments (given 0, expected 1))
# Tried to call [1, 2].+(), not 1.+(2), so no unpacking
```

Whilst lambda would behave this way:
```ruby
PLUS_L = lambda { |obj, *rest| obj.send(:+, *rest) }
PLUS_L.call(1, 2)
# => 3 
PLUS_L.call([1, 2])
# ArgumentError (wrong number of arguments (given 0, expected 1))

# Explicit return:
lambda { |obj, *rest| return obj.send(:+, *rest) }.call(1, 2)
# => 3
```
....and proc will behave this way:
```ruby
PLUS_P = lambda { |obj, *rest| obj.send(:+, *rest) }
PLUS_P.call(1, 2)
# => 3 
PLUS_P.call([1, 2])
# => 3 
# Implicit unpacking

# Explicit return:
proc { |obj, *rest| return obj.send(:+, *rest) }.call(1, 2)
# --- returns from the enclosing scope
```

So, `:<sym>.to_proc` behaves *exactly* like lambda, and *nothing* like proc.

The only thing that differs from the equivalent lambda is...
```ruby
PLUS.parameters # => [[:rest]]
PLUS_L.parameters # => [[:req, :obj], [:rest, :rest]]
```
(which is ideally to be fixed too, as in fact the first parameter is indeed mandatory.)

Can you please show me the case when `:<sym>.to_proc` does NOT behave like lambda?..

> Just curious: How do you want to use the result of `lambda?`?

@mame For explanatory and educational purposes, at least. For example, in [this article](https://zverok.github.io/blog/2019-10-18-each_with_object.html), I am showing some funny examples, and to explain why this works:
```ruby
[1, 2, 3].zip([4, 4, 4]).map { |a, b| a + b }
```
...and this not:
```ruby
[1, 2, 3].zip([4, 4, 4]).map(&:+)
```
...I'd like to just say "because `:+.to_proc` is a lambda, as you can see", but what I really need to say is "becuase `:+.to_proc` doesn't unpacks arguments, behaving like lambda... though it doesn't aknowledge it is"".

So, yep, debugging, explaining, teaching, this kind of things. 

----------------------------------------
Misc #16260: Symbol#to_proc behaves like lambda, but doesn't aknowledge it
https://bugs.ruby-lang.org/issues/16260#change-83240

* Author: zverok (Victor Shepelev)
* Status: Rejected
* Priority: Normal
* Assignee: 
----------------------------------------
Seems that `Symbol#to_proc` returns `Proc` that has lambda semantics:
```ruby
proc = :+.to_proc
proc.call(1, 2)   # => 3
proc.call([1, 2]) # ArgumentError (wrong number of arguments (given 0, expected 1))
```
But if you ask...
```ruby
proc.lambda? # => false
```

That seems to be an inconsistency, which I'd like to clarify. There are obviously two ways to fix it:
1. Make it respond `true` to `lambda?` (and mention the semantics in docs)
2. Make it behave like non-lambda.

The second one seems to produce some useful behavior:
```ruby
# Currently:
[1, 2].zip([3, 4]).map(&:+) # ArgumentError (wrong number of arguments (given 0, expected 1))

# With non-lambda:
class Symbol
  def to_proc
    proc { |o, *a| o.send(self, *a) }
  end
end

[1, 2].zip([3, 4]).map(&:+) # => [4, 6] 
```

Probably all of it was discussed when `Symbol#to_proc` was introduced, but as old NEWS-files doesn't link to tickets/discussions, I can't find the reasoning for current behavior.



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