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


Eregon (Benoit Daloze) wrote:
> The code around there looks like:
> 
> ```ruby
> def seplist(list, sep=nil, iter_method=:each) # :yield: element
>   sep ||= lambda { comma_breakable }
>   first = true
>   list.__send__(iter_method) {|*v|
>     if first
>       first = false
>     else
>       sep.call
>     end
>     yield(*v) # warning: Passing the keyword argument as the last hash parameter is deprecated
>   }
> end
> 
> class Array # :nodoc:
>   def pretty_print(q) # :nodoc:
>   q.group(1, '[', ']') {
>     q.seplist(self) {|v| # warning: The called method is defined here
>       q.pp v
>     }
>   }
>   end
> end
> ```
> I don't know why it goes wrong.

It goes wrong because a `ruby2_keywords` flagged hash is passed where a regular positional argument is expected.  This is the the condition I warned about in #16463, the reason I am against `ruby2_keywords` by default.  As I stated there, "I think such magical behavior is likely to introduce difficult to diagnose breakage in some cases, with no obvious reason why the code is not working correctly." To paraphrase @Eregon , if a ruby committer heavily involved in the process cannot figure out even why a problem occurs, let alone the solution, what chance does a standard ruby programmer have?

I think @matz should strongly consider this particular problem when deciding whether to accept `ruby2_keywords` by default.  In @Eregon 's dev meeting presentation, he said of this type of code: "In some rare cases, users might want to treat keyword arguments as positional".  Perhaps this type of code is not as rare as once believed.

Fix for this case is in https://github.com/ruby/ruby/pull/2855

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

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* 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>