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


This story is rather different from Hash#each in #14015.

`Hash#each` has yielded an array that has a key and a value since a long time ago:

```
# 2.7
{ a: 1 }.each {|a| p a } #=> [:a, 1]
```

BTW, `Hash#each` has an optimization to skip array generation if the arity of a given block is 2. However, this optimization had overlooked the case where the block is lambda. This is a bug of optimization. #14015 pointed out this issue, and we fixed it:

```
# 2.7
{ a: 1 }.each(&->(k, v){ p k }) #=> :a # the bug that #14015 pointed out

# the current master
{ a: 1 }.each(&->(k, v){ p k }) #=> wrong number of arguments (given 1, expected 2)
```

This is incompatible, but it changes only the case where a lambda block is passed to `Hash#each` (which is relatively rare, I think), so I (hopefully) guess it is acceptable, and we have no bug report about this since preview-1.

On the other hand, `Hash#select` has yielded two elements since Ruby 1.9.0:

```
# 2.7
{ a: 1 }.select {|k| p k } #=> :a

# this proposal
{ a: 1 }.select {|k| p k } #=> [:a, 1]
```

IMO, this is a bug since 1.9.0 because Hash#select looks like a faster version of Enumerable#select, so it should behave as possible as like Enumerable#select. However, the behavior has been longly accepted anyway, and passing a plain (non-lambda) block to Hash#select is the main use case, so fixing this may have a bigger impact than `Hash#each`.

In short: I like the proposal, but the imcompatibility would be much bigger than #14015.

----------------------------------------
Bug #17197: Some Hash methods still have arity 2 instead of 1
https://bugs.ruby-lang.org/issues/17197#change-88514

* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: nobu (Nobuyoshi Nakada)
* ruby -v: ruby 3.0.0dev (2020-09-26T17:38:39Z master 950614b088)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
`Hash#each` was changed recently to have arity of 1.
All other methods of `Hash` should behave the same.
Much has been fixed since #14015, but some remains:

```ruby
# Some methods consistently have arity 2:
{a: 1}.select( &->(_kvp) {} ) # => ArgumentError (wrong number of arguments (given 2, expected 1))
```

All in all: `%i[select keep_if delete_if reject to_h]` have their arity still set at 2.




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