ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: daniel@dan42.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:96059] [Ruby master Feature#16166] Remove exceptional treatment of *foo when it is the sole block parameter
Date: Mon, 02 Dec 2019 15:55:30 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-82905.20191202155529.b6d9d5a4b97fa48b@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16166.20190913081711@ruby-lang.org

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>

  parent reply	other threads:[~2019-12-02 15:55 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [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 ` daniel [this message]
2020-01-05 16:06 ` [ruby-core:96671] " sawadatsuyoshi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-82905.20191202155529.b6d9d5a4b97fa48b@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).