[ruby-core:96328] [Ruby master Misc#16260] Symbol#to_proc behaves like lambda, but doesn't aknowledge it

[email protected]
Newsgroups gmane.comp.lang.ruby.core
Message-ID <redmine.journal-83240.20191219092359.89b9d755f7314b90@ruby-lang.org>
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:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.