Bug #18289
closedEnumerable#to_a should delegate keyword arguments to #each
Description
Enumerable#to_a has always delegated its arguments to #each, but it does not handle keyword arguments. This seems like an oversight.
My project uses keyword arguments to an #each method, and this has broken Enumerable#to_a as of ruby 3 (and generates a warning on ruby 2.7).
class Foo
include Enumerable
def each(opt: )
yield 'foo'
end
end
pp Foo.new.to_a(opt: 4)
ruby 2.4
["foo"]
ruby 2.7
to_a_kw_arg_delegation.rb:8: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
to_a_kw_arg_delegation.rb:3: warning: The called method `each' is defined here
["foo"]
ruby 3
to_a_kw_arg_delegation.rb:3:in `each': wrong number of arguments (given 1, expected 0; required keyword: opt) (ArgumentError)
from to_a_kw_arg_delegation.rb:8:in `to_a'
from to_a_kw_arg_delegation.rb:8:in `<main>'
Files
Updated by jeremyevans0 (Jeremy Evans) almost 4 years ago
I've submitted a pull request to fix this: https://github.com/ruby/ruby/pull/5086
Updated by jeremyevans0 (Jeremy Evans) almost 4 years ago
- Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: DONTNEED, 2.7: REQUIRED, 3.0: REQUIRED
Updated by jeremyevans (Jeremy Evans) almost 4 years ago
- Status changed from Open to Closed
Applied in changeset git|e83c02a768af61cd0890a75e90bcae1119d8bd93.
Delegate keywords from Enumerable#to_a to #each
Fixes [Bug #18289]
Updated by nobu (Nobuyoshi Nakada) almost 4 years ago
Recently I've encountered similar issue with grep(regexp, chomp: true).
And IO#each has the separator and limit arguments, I wonder how to pass them.
Updated by jeremyevans0 (Jeremy Evans) almost 4 years ago
nobu (Nobuyoshi Nakada) wrote in #note-4:
Recently I've encountered similar issue with
grep(regexp, chomp: true).
What's the issue with grep? If it is a keyword issue, we can probably fix it.
And
IO#eachhas the separator and limit arguments, I wonder how to pass them.
IO#each doesn't use keywords, so to_a should pass the arguments even before e83c02a768af61cd0890a75e90bcae1119d8bd93:
$ echo 'aaa\nbbb\nccc' | ruby -ve 'p $stdin.to_a("\n", 2)'
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-openbsd]
["aa", "a\n", "bb", "b\n", "cc", "c\n"]
Updated by nobu (Nobuyoshi Nakada) almost 4 years ago
jeremyevans0 (Jeremy Evans) wrote in #note-5:
nobu (Nobuyoshi Nakada) wrote in #note-4:
Recently I've encountered similar issue with
grep(regexp, chomp: true).What's the issue with
grep? If it is a keyword issue, we can probably fix it.
Same as this issue.
And
IO#eachhas the separator and limit arguments, I wonder how to pass them.
IO#eachdoesn't use keywords, soto_ashould pass the arguments even before e83c02a768af61cd0890a75e90bcae1119d8bd93:
As the number of arguments of #grep is fixed, it won't be a problem in this case.
And #to_a has delegated all arguments to #each, so it didn't have problems.
But what about methods which have optional parameters, e.g. Enumerable#count?
Although it's possible to make the first argument mandatory when passing arguments for #each, it doesn't feel very nice.
Updated by jeremyevans0 (Jeremy Evans) almost 4 years ago
grep doesn't appear to have the same issue as to_a, since it explicitly calls each with no arguments (unlike to_a, which delegates arguments to each). Same thing with count. So I'm not sure what the issue is in the grep or count cases. Could you give an example in code showing the problem?
Updated by nagachika (Tomoyuki Chikanaga) almost 4 years ago
- Backport changed from 2.6: DONTNEED, 2.7: REQUIRED, 3.0: REQUIRED to 2.6: DONTNEED, 2.7: REQUIRED, 3.0: DONE
ruby_3_0 aadb8cad563ca23e54a775d4fee936a07466112f merged revision(s) e83c02a768af61cd0890a75e90bcae1119d8bd93.
Updated by usa (Usaku NAKAMURA) almost 4 years ago
- Backport changed from 2.6: DONTNEED, 2.7: REQUIRED, 3.0: DONE to 2.6: DONTNEED, 2.7: DONE, 3.0: DONE
ruby_2_7 b1985629565c3c54b1a64d6faf213e8144857515 merged revision(s) e83c02a768af61cd0890a75e90bcae1119d8bd93.