ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:94925] [Ruby master Feature#16166] Remove exceptional handling of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
@ 2019-09-13  8:17 ` sawadatsuyoshi
  2019-09-13 10:16 ` [ruby-core:94926] [Ruby master Feature#16166] Remove exceptional treatment " mame
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: sawadatsuyoshi @ 2019-09-13  8:17 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been reported by sawa (Tsuyoshi Sawada).

----------------------------------------
Feature #16166: Remove exceptional handling of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166

* 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 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 handling of a 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/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:94926] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
  2019-09-13  8:17 ` [ruby-core:94925] [Ruby master Feature#16166] Remove exceptional handling of *foo when it is the sole block parameter sawadatsuyoshi
@ 2019-09-13 10:16 ` mame
  2019-09-13 15:44 ` [ruby-core:94929] " shevegen
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: mame @ 2019-09-13 10:16 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by mame (Yusuke Endoh).


I agree that Ruby's arguments are insanely complex.  In the basic case, `"a"` and `["a"]` are distinguished.

```
p instance_exec("a")  {|foo| foo } #=> "a"
p instance_exec(["a"]){|foo| foo } #=> ["a"]

p instance_exec("a")  {|*foo| foo } #=> ["a"]
p instance_exec(["a"]){|*foo| foo } #=> [["a"]]
```

In *some* cases, they are not distinguished.

```
p instance_exec("a")  {|foo, bar| foo } #=> "a"
p instance_exec(["a"]){|foo, bar| foo } #=> "a"

p instance_exec(["a"]){|*foo, **bar| foo } #=> ["a"]
p instance_exec("a")  {|*foo, **bar| foo } #=> ["a"]
```

The rule is fairly complex or even inconsistent.  I cannot understand [the condition](https://github.com/ruby/ruby/blob/5f5aca1b5fb95013f5b805f74ead4cfa143dc1d8/vm_args.c#L765-L769).

I have no opinion which case `|*foo|` should belong to.  (I personally hope that `|*foo, **bar|` belongs to the same case as `|*foo|` because keywords are separated from positional arguments.)

Anyway, I don't think that it is a good idea to change the behavior just because it is inconsistent.  We need an evidence that the behavior actually confuses many people, at least.

----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-81542

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:94929] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
  2019-09-13  8:17 ` [ruby-core:94925] [Ruby master Feature#16166] Remove exceptional handling of *foo when it is the sole block parameter sawadatsuyoshi
  2019-09-13 10:16 ` [ruby-core:94926] [Ruby master Feature#16166] Remove exceptional treatment " mame
@ 2019-09-13 15:44 ` shevegen
  2019-09-13 15:45 ` [ruby-core:94930] " shevegen
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: shevegen @ 2019-09-13 15:44 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by shevegen (Robert A. Heiler).


> We need an evidence that the behavior actually confuses
> many people, at least.

It does not confuse me because ... I try to avoid it altogether. :D

I think sawa's issue can be a bit shortened (sorry!) to the last
comparison:

    instance_exec(["a"]){|*foo| foo} # => [["a"]]
    instance_exec(["a"]){|*foo| foo} # => ["a"]

Although I may miss (or not completely understand) all of the reasoning,
I think that change would make sense (to me) - but I may not understand
the consequences.

I only remember even matz having fun in a presentation with the 
whole keyword arg situation before. ;) (One reason why I try to
actually avoid keywords is because I find them more difficult to
deal/cope with than oldschool options hash. But I guess this may
differ from ruby user to ruby user since it is a personal preference.)

Perhaps there should be a simple and consistent rule for how * and **
is to be interpreted at all times, including what should happen if
both are used at the same time. What I find indeed a bit confusing
is that * changes if ** is also used. That part is very strange to
me personally. Might also be mentioned in the documentation, but 
for me personally, I gladly stick to the simpler variants. :D

----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-81545

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:94930] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2019-09-13 15:44 ` [ruby-core:94929] " shevegen
@ 2019-09-13 15:45 ` shevegen
  2019-09-25  3:00 ` [ruby-core:95073] " matz
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: shevegen @ 2019-09-13 15:45 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by shevegen (Robert A. Heiler).


Actually that reminds me - mame mentioned that the ruby core team needs a
motivation/impetus if a change is necessary based on real usage. So I think
this may be a good call for ruby users to comment in particular when it
may affect them (either way) in actual code. Me personally I am not affected
in either way, but it may be a good idea to get a survey/query to ruby users
out there to comment, in particular when it may affect them in their own 
code base or a code base they use/depend on.

----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-81546

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:95073] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2019-09-13 15:45 ` [ruby-core:94930] " shevegen
@ 2019-09-25  3:00 ` matz
  2019-09-27 23:03 ` [ruby-core:95139] " merch-redmine
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: matz @ 2019-09-25  3:00 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by matz (Yukihiro Matsumoto).


I think the following code behavior is wrong:
```ruby
p instance_exec(["a"]){|*foo, **bar| foo } #=> ["a"]
```
It should return `[["a"]]`.

Matz.


----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-81705

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:95139] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2019-09-25  3:00 ` [ruby-core:95073] " matz
@ 2019-09-27 23:03 ` merch-redmine
  2019-10-22 18:00 ` [ruby-core:95472] " daniel
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: merch-redmine @ 2019-09-27 23:03 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by jeremyevans0 (Jeremy Evans).


matz (Yukihiro Matsumoto) wrote:
> I think the following code behavior is wrong:
> ```ruby
> p instance_exec(["a"]){|*foo, **bar| foo } #=> ["a"]
> ```
> It should return `[["a"]]`.

Here's a pull request for that: https://github.com/ruby/ruby/pull/2502

Note that it breaks some tests/specs.  I believe the reason methods with keywords were handled differently is because the last element of the argument could be used as keywords:

```
$ ruby -e "p proc{|*foo, **bar| [foo, bar]}.call([1, {a: 1}])"
-e:1: warning: The last argument is used as the keyword parameter
-e:1: warning: for `call' defined here
[[1], {:a=>1}]
```

As you can see, this now raises a warning in Ruby 2.7, and behavior will change in Ruby 3.0.  Do we want to make this change in 2.7, or do we want to wait for 3.0?


----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-81778

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:95472] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2019-09-27 23:03 ` [ruby-core:95139] " merch-redmine
@ 2019-10-22 18:00 ` daniel
  2019-11-27 17:55 ` [ruby-core:95996] " eregontp
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: daniel @ 2019-10-22 18:00 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by Dan0042 (Daniel DeLorme).


I think this is related:

```ruby
proc{ |a,b| [a,b] }.call(1,2)   #=> [1, 2]
proc{ |*ab| ab    }.call(1,2)   #=> [1, 2]
proc{ |a,b| [a,b] }.call([1,2]) #=> [1, 2]
proc{ |*ab| ab    }.call([1,2]) #=> [[1, 2]]
```

I *really* think the last result should be [1, 2]. Otherwise I totally fail to understand the logic. But of course there's always backward compatibility to worry about...

----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-82242

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:95996] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2019-10-22 18:00 ` [ruby-core:95472] " daniel
@ 2019-11-27 17:55 ` eregontp
  2019-12-02 15:55 ` [ruby-core:96059] " daniel
  2020-01-05 16:06 ` [ruby-core:96671] " sawadatsuyoshi
  9 siblings, 0 replies; 10+ messages in thread
From: eregontp @ 2019-11-27 17:55 UTC (permalink / raw)
  To: ruby-core

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


@sawa wrote this in the dev-meeting ticket:
> Unintended arity. This must be fixed in an earlier stage before Ruby 3.

I think matz conclusion is all behavior shown in this bug so far is intended, except for `*foo, **bar`.

@Dan0042
```
proc{ |a,b| [a,b] }.call(1,2)   #=> [1, 2]
proc{ |*ab| ab    }.call(1,2)   #=> [1, 2]
proc{ |a,b| [a,b] }.call([1,2]) #=> [1, 2]
proc{ |*ab| ab    }.call([1,2]) #=> [[1, 2]]
```
That's just how Proc works, multiple parameters will splat an Array if a single Array argument is given.

I think long-term we might want to use lambda semantics by default for blocks, which doesn't have that splatting magic.

----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-82832

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:96059] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (7 preceding siblings ...)
  2019-11-27 17:55 ` [ruby-core:95996] " eregontp
@ 2019-12-02 15:55 ` daniel
  2020-01-05 16:06 ` [ruby-core:96671] " sawadatsuyoshi
  9 siblings, 0 replies; 10+ messages in thread
From: daniel @ 2019-12-02 15:55 UTC (permalink / raw)
  To: ruby-core

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>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:96671] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
       [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
                   ` (8 preceding siblings ...)
  2019-12-02 15:55 ` [ruby-core:96059] " daniel
@ 2020-01-05 16:06 ` sawadatsuyoshi
  9 siblings, 0 replies; 10+ messages in thread
From: sawadatsuyoshi @ 2020-01-05 16:06 UTC (permalink / raw)
  To: ruby-core

Issue #16166 has been updated by sawa (Tsuyoshi Sawada).


[The log for developers' meeting 20191128](https://docs.google.com/document/d/1AZ74HXEedKksJwhEUPIlnRxAUgchndZPZYAKjGPMsFI/edit#) says that Matz hoped this to be done in 2.7. However, Ruby 2.7 still returns this:

```ruby
instance_exec(["a"]){|*foo, **bar| foo } #=> ["a"]
```

Likely forgotten? Perhaps, it can be done by the next release (2.8 or 3.0).

----------------------------------------
Feature #16166: Remove exceptional treatment of *foo when it is the sole block parameter
https://bugs.ruby-lang.org/issues/16166#change-83654

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-01-05 16:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-16166.20190913081711@ruby-lang.org>
2019-09-13  8:17 ` [ruby-core:94925] [Ruby master Feature#16166] Remove exceptional handling of *foo when it is the sole block parameter sawadatsuyoshi
2019-09-13 10:16 ` [ruby-core:94926] [Ruby master Feature#16166] Remove exceptional treatment " mame
2019-09-13 15:44 ` [ruby-core:94929] " shevegen
2019-09-13 15:45 ` [ruby-core:94930] " shevegen
2019-09-25  3:00 ` [ruby-core:95073] " matz
2019-09-27 23:03 ` [ruby-core:95139] " merch-redmine
2019-10-22 18:00 ` [ruby-core:95472] " daniel
2019-11-27 17:55 ` [ruby-core:95996] " eregontp
2019-12-02 15:55 ` [ruby-core:96059] " daniel
2020-01-05 16:06 ` [ruby-core:96671] " sawadatsuyoshi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).