ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:107900] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially
@ 2022-03-14 17:36 Eregon (Benoit Daloze)
  2022-03-14 17:41 ` [ruby-core:107903] " Eregon (Benoit Daloze)
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Eregon (Benoit Daloze) @ 2022-03-14 17:36 UTC (permalink / raw
  To: ruby-core

Issue #18633 has been reported by Eregon (Benoit Daloze).

----------------------------------------
Bug #18633: proc { |a, **kw| a } autosplats and treats empty kwargs specially
https://bugs.ruby-lang.org/issues/18633

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
```ruby
irb(main):005:0> proc { |a| a }.call([1, 2])
=> [1, 2]
irb(main):006:0> proc { |a, **kw| a }.call([1, 2])
=> 1 # should be [1, 2]
irb(main):007:0> proc { |a, kw: 42| a }.call([1, 2])
=> 1 # should be [1, 2]
```

What's the reason for `proc { |a, **kw| a }` to autosplat?
It seems inconsistent with the resolution of #16166, and it seems nobody would want that behavior (it loses arguments but the user extremely likely did not want that).
Could we change it so procs never autosplat, just like `proc { |a| a }`.

My understanding of the change in #16166 is to reflect the fact positional and kwargs are separated, and so adding `**kw` or `kw:` should never change anything if only positional arguments are passed.
This breaks in this case though.

Also I noticed:
```ruby
irb(main):010:0> proc { |a, **kw| a }.call([1, 2])
=> 1
irb(main):011:0> proc { |a, **kw| a }.call([1, 2], **{})
=> [1, 2]
```
Which is really unfortunate as it shows a difference between passing `**{}` or nothing.
AFAIK passing `**{}` or nothing should always be equivalent, but it breaks in this case.

(from https://bugs.ruby-lang.org/issues/16166#note-14)



-- 
https://bugs.ruby-lang.org/

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

* [ruby-core:107903] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially
  2022-03-14 17:36 [ruby-core:107900] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially Eregon (Benoit Daloze)
@ 2022-03-14 17:41 ` Eregon (Benoit Daloze)
  2022-03-14 22:47 ` [ruby-core:107905] " jeremyevans0 (Jeremy Evans)
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Eregon (Benoit Daloze) @ 2022-03-14 17:41 UTC (permalink / raw
  To: ruby-core

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


This is the logic in TruffleRuby, basically we can see the inconsistency and the need for a hack just to support this case:
```java
    private boolean shouldConsiderDestructuringArrayArg(Arity arity) {
        if (arity.getRequired() == 1 && arity.getOptional() == 0 && !arity.hasRest() && arity.hasKeywordsRest()) {
            // Special case for: proc { |a, **kw| a }.call([1, 2]) => 1
            // Seems inconsistent: https://bugs.ruby-lang.org/issues/18633
            return true;
        }

        if (!arity.hasRest() && arity.getRequired() + arity.getOptional() <= 1) {
            // If we accept at most 0 or 1 arguments, there's never any need to destructure
            return false;
        } else if (arity.hasRest() && arity.getRequired() == 0) {
            // If there are only a rest argument and optional arguments, there is no need to destructure.
            // Because the first optional argument (or the rest if no optional) will take the whole array.
            return false;
        } else {
            return true;
        }
    }
```

Whether a Proc should autosplat besides special case is otherwise not too complicated.
The only runtime checks (in addition to these static checks) are:
* a single argument is passed, and it responds to `#to_ary`.
* if kwargs are passed, no autosplatting

----------------------------------------
Bug #18633: proc { |a, **kw| a } autosplats and treats empty kwargs specially
https://bugs.ruby-lang.org/issues/18633#change-96841

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
```ruby
irb(main):005:0> proc { |a| a }.call([1, 2])
=> [1, 2]
irb(main):006:0> proc { |a, **kw| a }.call([1, 2])
=> 1 # should be [1, 2]
irb(main):007:0> proc { |a, kw: 42| a }.call([1, 2])
=> 1 # should be [1, 2]
```

What's the reason for `proc { |a, **kw| a }` to autosplat?
It seems inconsistent with the resolution of #16166, and it seems nobody would want that behavior (it loses arguments but the user extremely likely did not want that).
Could we change it so procs never autosplat, just like `proc { |a| a }`.

My understanding of the change in #16166 is to reflect the fact positional and kwargs are separated, and so adding `**kw` or `kw:` should never change anything if only positional arguments are passed.
This breaks in this case though.

Also I noticed:
```ruby
irb(main):010:0> proc { |a, **kw| a }.call([1, 2])
=> 1
irb(main):011:0> proc { |a, **kw| a }.call([1, 2], **{})
=> [1, 2]
```
Which is really unfortunate as it shows a difference between passing `**{}` or nothing.
AFAIK passing `**{}` or nothing should always be equivalent, but it breaks in this case.

(from https://bugs.ruby-lang.org/issues/16166#note-14)



-- 
https://bugs.ruby-lang.org/

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

* [ruby-core:107905] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially
  2022-03-14 17:36 [ruby-core:107900] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially Eregon (Benoit Daloze)
  2022-03-14 17:41 ` [ruby-core:107903] " Eregon (Benoit Daloze)
@ 2022-03-14 22:47 ` jeremyevans0 (Jeremy Evans)
  2022-03-15 20:43 ` [ruby-core:107912] " jeremyevans0 (Jeremy Evans)
  2022-03-17  8:46 ` [ruby-core:107941] " matz (Yukihiro Matsumoto)
  3 siblings, 0 replies; 5+ messages in thread
From: jeremyevans0 (Jeremy Evans) @ 2022-03-14 22:47 UTC (permalink / raw
  To: ruby-core

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


Eregon (Benoit Daloze) wrote:
> ```ruby
> irb(main):005:0> proc { |a| a }.call([1, 2])
> => [1, 2]
> irb(main):006:0> proc { |a, **kw| a }.call([1, 2])
> => 1 # should be [1, 2]
> irb(main):007:0> proc { |a, kw: 42| a }.call([1, 2])
> => 1 # should be [1, 2]
> ```
> 
> What's the reason for `proc { |a, **kw| a }` to autosplat?
> It seems inconsistent with the resolution of #16166, and it seems nobody would want that behavior (it loses arguments but the user extremely likely did not want that).
> Could we change it so procs never autosplat, just like `proc { |a| a }`.

I agree that there is no reason to autosplat in this case on Ruby 3 (autosplatting made sense in Ruby 2).  I changed the `*a, **kw` case in #16166, because that is the case @matz indicated he wanted to change (https://bugs.ruby-lang.org/issues/16166#note-6).  @matz didn't indicate he wanted the behavior of `a, **kw` or `a, kw: ` changed, so I didn't make changes to that behavior.  

Like #18625, this change seems too risky to backport, and there doesn't seem to be a way to properly deprecate it.  So I also recommend we make this change in 3.2 and not backport it.

> Also I noticed:
> ```ruby
> irb(main):010:0> proc { |a, **kw| a }.call([1, 2])
> => 1
> irb(main):011:0> proc { |a, **kw| a }.call([1, 2], **{})
> => [1, 2]
> ```
> Which is really unfortunate as it shows a difference between passing `**{}` or nothing.
> AFAIK passing `**{}` or nothing should always be equivalent, but it breaks in this case.
> 
> (from https://bugs.ruby-lang.org/issues/16166#note-14)

At least this behavior is deliberate.  We don't want `proc { |a, **kw| a }.call([1, 2], **h)` to result in `a` sometimes being `1` and other times being `[1, 2]` based on the value of `h`.  Always using `[1, 2]` for `a` seems fine.

----------------------------------------
Bug #18633: proc { |a, **kw| a } autosplats and treats empty kwargs specially
https://bugs.ruby-lang.org/issues/18633#change-96843

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
```ruby
irb(main):005:0> proc { |a| a }.call([1, 2])
=> [1, 2]
irb(main):006:0> proc { |a, **kw| a }.call([1, 2])
=> 1 # should be [1, 2]
irb(main):007:0> proc { |a, kw: 42| a }.call([1, 2])
=> 1 # should be [1, 2]
```

What's the reason for `proc { |a, **kw| a }` to autosplat?
It seems inconsistent with the resolution of #16166, and it seems nobody would want that behavior (it loses arguments but the user extremely likely did not want that).
Could we change it so procs never autosplat, just like `proc { |a| a }`.

My understanding of the change in #16166 is to reflect the fact positional and kwargs are separated, and so adding `**kw` or `kw:` should never change anything if only positional arguments are passed.
This breaks in this case though.

Also I noticed:
```ruby
irb(main):010:0> proc { |a, **kw| a }.call([1, 2])
=> 1
irb(main):011:0> proc { |a, **kw| a }.call([1, 2], **{})
=> [1, 2]
```
Which is really unfortunate as it shows a difference between passing `**{}` or nothing.
AFAIK passing `**{}` or nothing should always be equivalent, but it breaks in this case.

(from https://bugs.ruby-lang.org/issues/16166#note-14)



-- 
https://bugs.ruby-lang.org/

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

* [ruby-core:107912] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially
  2022-03-14 17:36 [ruby-core:107900] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially Eregon (Benoit Daloze)
  2022-03-14 17:41 ` [ruby-core:107903] " Eregon (Benoit Daloze)
  2022-03-14 22:47 ` [ruby-core:107905] " jeremyevans0 (Jeremy Evans)
@ 2022-03-15 20:43 ` jeremyevans0 (Jeremy Evans)
  2022-03-17  8:46 ` [ruby-core:107941] " matz (Yukihiro Matsumoto)
  3 siblings, 0 replies; 5+ messages in thread
From: jeremyevans0 (Jeremy Evans) @ 2022-03-15 20:43 UTC (permalink / raw
  To: ruby-core

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


I've submitted a pull request to remove the autosplatting: https://github.com/ruby/ruby/pull/5665

----------------------------------------
Bug #18633: proc { |a, **kw| a } autosplats and treats empty kwargs specially
https://bugs.ruby-lang.org/issues/18633#change-96848

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
```ruby
irb(main):005:0> proc { |a| a }.call([1, 2])
=> [1, 2]
irb(main):006:0> proc { |a, **kw| a }.call([1, 2])
=> 1 # should be [1, 2]
irb(main):007:0> proc { |a, kw: 42| a }.call([1, 2])
=> 1 # should be [1, 2]
```

What's the reason for `proc { |a, **kw| a }` to autosplat?
It seems inconsistent with the resolution of #16166, and it seems nobody would want that behavior (it loses arguments but the user extremely likely did not want that).
Could we change it so procs never autosplat, just like `proc { |a| a }`.

My understanding of the change in #16166 is to reflect the fact positional and kwargs are separated, and so adding `**kw` or `kw:` should never change anything if only positional arguments are passed.
This breaks in this case though.

Also I noticed:
```ruby
irb(main):010:0> proc { |a, **kw| a }.call([1, 2])
=> 1
irb(main):011:0> proc { |a, **kw| a }.call([1, 2], **{})
=> [1, 2]
```
Which is really unfortunate as it shows a difference between passing `**{}` or nothing.
AFAIK passing `**{}` or nothing should always be equivalent, but it breaks in this case.

(from https://bugs.ruby-lang.org/issues/16166#note-14)



-- 
https://bugs.ruby-lang.org/

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

* [ruby-core:107941] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially
  2022-03-14 17:36 [ruby-core:107900] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially Eregon (Benoit Daloze)
                   ` (2 preceding siblings ...)
  2022-03-15 20:43 ` [ruby-core:107912] " jeremyevans0 (Jeremy Evans)
@ 2022-03-17  8:46 ` matz (Yukihiro Matsumoto)
  3 siblings, 0 replies; 5+ messages in thread
From: matz (Yukihiro Matsumoto) @ 2022-03-17  8:46 UTC (permalink / raw
  To: ruby-core

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


Should be fixed. Review the patch and merge it if it's OK. @nobu please?

Matz.


----------------------------------------
Bug #18633: proc { |a, **kw| a } autosplats and treats empty kwargs specially
https://bugs.ruby-lang.org/issues/18633#change-96891

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
```ruby
irb(main):005:0> proc { |a| a }.call([1, 2])
=> [1, 2]
irb(main):006:0> proc { |a, **kw| a }.call([1, 2])
=> 1 # should be [1, 2]
irb(main):007:0> proc { |a, kw: 42| a }.call([1, 2])
=> 1 # should be [1, 2]
```

What's the reason for `proc { |a, **kw| a }` to autosplat?
It seems inconsistent with the resolution of #16166, and it seems nobody would want that behavior (it loses arguments but the user extremely likely did not want that).
Could we change it so procs never autosplat, just like `proc { |a| a }`.

My understanding of the change in #16166 is to reflect the fact positional and kwargs are separated, and so adding `**kw` or `kw:` should never change anything if only positional arguments are passed.
This breaks in this case though.

Also I noticed:
```ruby
irb(main):010:0> proc { |a, **kw| a }.call([1, 2])
=> 1
irb(main):011:0> proc { |a, **kw| a }.call([1, 2], **{})
=> [1, 2]
```
Which is really unfortunate as it shows a difference between passing `**{}` or nothing.
AFAIK passing `**{}` or nothing should always be equivalent, but it breaks in this case.

(from https://bugs.ruby-lang.org/issues/16166#note-14)



-- 
https://bugs.ruby-lang.org/

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

end of thread, other threads:[~2022-03-17  8:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-14 17:36 [ruby-core:107900] [Ruby master Bug#18633] proc { |a, **kw| a } autosplats and treats empty kwargs specially Eregon (Benoit Daloze)
2022-03-14 17:41 ` [ruby-core:107903] " Eregon (Benoit Daloze)
2022-03-14 22:47 ` [ruby-core:107905] " jeremyevans0 (Jeremy Evans)
2022-03-15 20:43 ` [ruby-core:107912] " jeremyevans0 (Jeremy Evans)
2022-03-17  8:46 ` [ruby-core:107941] " matz (Yukihiro Matsumoto)

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