[ruby-core:96059] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
From:
daniel@...42.com
Date:
2019-12-02 15:55:30 UTC
List:
ruby-core #96059
Issue #16166 has been updated by Dan0042 (Daniel DeLorme).
Eregon (Benoit Daloze) wrote:
> The `*rest` parameter will not splat either, or it would delegate arguments incorrectly.
Thanks! Finally I can see some meaning behind the madness. Normally I would expect `proc{ |*a| }.call([1,2])` to behave like the assignment `*a = [1,2]` but it does not. But now I can see that `proc{ |*a| foo(*a) }.call(arg1)` would not work if `arg1` happened to be an array.
However I still believe that the current behavior for `proc{ |*a| }` is wrong. If you want that particular case of delegation to work you should simply use a lambda instead of a proc. Having that special exception where a proc behaves like a lambda just for `*rest`... it makes things overly complicated. I mean, even mame says he cannot understand the condition! With all due respect to Matz, this would be much simpler if we could say that all procs behave with assignment semantics, and lambdas with parameter semantics.
Of course the backward compatibility is an issue but that can be handled with proper deprecation warnings. I think that would be a worthwhile change for ruby. My 2
----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-82905
* Author: sawa (Tsuyoshi Sawada)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
----------------------------------------
In the parameter signature of a code block for a method that is not involved in method definition or creation of lambda objects, two types of arguments `["a"]` and `"a"` are neutralized:
```ruby
instance_exec(["a"]){|foo, bar| foo} # => "a"
instance_exec("a"){|foo, bar| foo} # => "a"
instance_exec(["a"]){|*foo, **bar| foo} # => ["a"]
instance_exec("a"){|*foo, **bar| foo} # => ["a"]
```
This is the same behavior as with assignment constructions:
```ruby
foo, bar = ["a"]; foo # => "a"
foo, bar = "a"; foo # => "a"
*foo = ["a"]; foo # => ["a"]
*foo = "a"; foo # => ["a"]
```
And it contrasts with constructions involved in method definition or creation of lambda objects, where the distinction is preserved:
```ruby
lambda{|foo| foo}.call(["a"]) # => ["a"]
lambda{|foo| foo}.call("a") # => "a"
->(foo){foo}.call(["a"]) # => ["a"]
->(foo){foo}.call("a") # => "a"
lambda{|*foo| foo}.call(["a"]) # => [["a"]]
lambda{|*foo| foo}.call("a") # => ["a"]
->(*foo){foo}.call(["a"]) # => [["a"]]
->(*foo){foo}.call("a") # => ["a"]
```
However, when `*foo` is the sole parameter of a code block for a method that is not involved in method definition or creation of lambda objects, `["a"]` and `"a"` are not neutralized:
```ruby
instance_exec(["a"]){|*foo| foo} # => [["a"]]
instance_exec("a"){|*foo| foo} # => ["a"]
```
behaving in contrast to assignment constructions, and rather on a par with constructions involved in method definition or creation of lambda objects.
Particularly, existence or absence of another parameter `**bar` entirely changes what `foo` refers to:
```ruby
instance_exec(["a"]){|*foo| foo} # => [["a"]]
instance_exec(["a"]){|*foo, **bar| foo} # => ["a"]
```
I find this behavior inconsistent and confusing. I would like to request to remove this exceptional treatment of splatted parameter `*foo` when it is the sole parameter in a code block. I request this behavior:
```ruby
instance_exec(["a"]){|*foo| foo} # => ["a"]
```
--
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>