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


jeremyevans0 (Jeremy Evans) wrote in #note-12:
> Having a double splatted empty hash be removed is necessary for delegation to work correctly

Except that, no, it's _not_ necessary, and I have the proof of concept to prove it.

> Additionally, the behavior is more consistent with explicit keywords:

I agree it's more consistent if an empty hash splat always behaves the same way, but in my experiment I've found this inconsistency to be surprisingly non-confusing. "there is a non-neglectable gap between what is "consistent" for computers, and what is "consistent" for humans." -- zverok

Also, it looks convincing when you use an empty splat literal like `**{}` in your examples, but you have to look at cases when splatting an empty hash is actually going to happen. There's delegation of course, and there's also the case of building an options hash based on conditions, as shown above. If you have `foo(**hash)` and you can't predict the behavior because it depends on the hash contents, I consider that a problem worse than inconsistency.

> In my mind, if you have a mandatory argument, and you don't pass an argument to it, it should be an ArgumentError.  This is the same for regular splats:

In my mind, if you have a mandatory _keyword_ argument, and you don't pass a _keyword_ argument to it, it should be an ArgumentError (and it is). An empy kw-splat is equivalent to "no keyword argument", but _not_ to "no positional argument". Because keyword and positional are separated. When passing a kw-splat to a positional-only method, you're not really passing keywords, but a positional Hash; it should be like ignoring the kw-splat part (but dup'ing the hash) because the method doesn't support keywords.

I've shown behavior that works in 2.6 and breaks in 2.7, but your response seems to be that **it doesn't matter**, because it's "unlikely" to happen or the code was already "basically broken" (even though it worked in the example). I must say I find that very frustrating; it's not possible to make an argument if all those demonstrated incompatibilities don't even matter or exist in your eyes. :-/

(btw thanks for your replies; I am frustrated but grateful)


----------------------------------------
Bug #16519: pp [Hash.ruby2_keywords_hash({})] shows `[nil]`
https://bugs.ruby-lang.org/issues/16519#change-84127

* Author: Eregon (Benoit Daloze)
* Status: Closed
* Priority: Normal
* ruby -v: ruby 2.8.0dev (2020-01-21T13:45:10Z master 5798d35ff6) [x86_64-linux]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: REQUIRED
----------------------------------------
This happens on `master`:

```
$ ruby -ve 'ruby2_keywords def flag(*a); a.last; end; pp [flag(**{})]'
ruby 2.8.0dev (2020-01-21T13:45:10Z master 5798d35ff6) [x86_64-linux]
[nil]
```

Of course it should be `[{}]`, as it is for `pp [{}]`.

On 2.7.0 it warns (should be fixed, it's valid to `pp` a flagged Hash):
```
$ ruby -ve 'ruby2_keywords def flag(*a); a.last; end; pp [flag(**{})]'
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
[/home/eregon/.rubies/ruby-2.7.0/lib/ruby/2.7.0/pp.rb:226: warning: Passing the keyword argument as the last hash parameter is deprecated
/home/eregon/.rubies/ruby-2.7.0/lib/ruby/2.7.0/pp.rb:334: warning: The called method is defined here
{}]
```

The warning being in the middle of the output is a fun fact here.
Lines it refers to (still the same on current master):
https://github.com/ruby/ruby/blob/v2_7_0/lib/pp.rb#L226
https://github.com/ruby/ruby/blob/v2_7_0/lib/pp.rb#L334

This is very confusing as it can happen during `test-all` and then show output such as:
```
<[{:a=>1}]> expected but was
<[{:a=>1}, nil]>.
```
when the reality is (can be verified with `p` before the `assert_equal`):
```
<[{:a=>1}]> expected but was
<[{:a=>1}, {}]>.
```



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