Bug #19983
closed
Nested `*` seems incorrect
Added by Eregon (Benoit Daloze) about 1 year ago.
Updated 11 months ago.
ruby -v:
ruby 3.3.0dev (2023-10-30T09:27:06Z master 14fa5e39d7) [x86_64-linux]
[ruby-core:115212]
Description
$ ruby -v -e 'def m(*); ->(*) { p(*) }; end; m(1).call(2)'
ruby 3.3.0dev (2023-10-30T09:27:06Z master 14fa5e39d7) [x86_64-linux]
1
But I would expect 2
.
Much like:
$ ruby -e 'def m(a); ->(a) { p(a) }; end; m(1).call(2)'
ruby 3.3.0dev (2023-10-30T09:27:06Z master 14fa5e39d7) [x86_64-linux]
2
i.e. the inner variable should win.
Also affects at least 3.2.
- Description updated (diff)
I don't think you can forward arguments from lambdas at all, which is making this confusing.
->(*) { foo(*) }
# => (irb):1: no anonymous rest parameter (SyntaxError)
Procs don't support anonymous arguments (e.g. to pass them further), see #19370.
->(*) { p(*) }.call(1)
# no anonymous rest parameter (SyntaxError)
So, the code is equivalent to
def m(*); ->(_) { p(*) }; end; m(1).call(2)
So, the *
refers to the method's parameters.
(Unless I am missing something and support was added into 3.3)
If procs don't support *
then def m(*); ->(*) { p(*) }; end
should be SyntaxError.
It is incredibly confusing indeed that the *
parameter in the method and lambda has completely different behavior here.
->(*) {}
being a syntax error would break backward compatibility, since ->(*) {}
has always been allowed. It's not different from ->(foo, *, bar) {}
.
Right, maybe it should be SyntaxError only if there is a *
used inside a lambda/proc body (as a value), where the lambda/proc declares a *
parameter (like def m(*); ->(*) { p(*) }; end
).
IOW when using *
both in method and block scopes, where the block scope is inside the method scope.
I honestly believe it would be more reasonable to allow anonymous argument handling for procs, too.
It would be consistent and clear, no special edge cases due to, say, code copying (yes, there would be edge cases to demonstrate "how confusing you can make the code by abusing the feature," but such demonstrations could be made with Ruby 1.8.6 too).
I believe that shadowing of unnamed arguments is not more confusing than shadowing of named arguments, which Ruby always allowed.
Agreed, I think supporting *
fully for blocks would be a good way to solve this.
If that's deemed not desirable, then I think such code should be SyntaxError to avoid confusion and make it clear what works and does not.
- Subject changed from Nested * seems incorrect to Nested `*` seems incorrect
- Backport changed from 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN to 3.0: DONTNEED, 3.1: DONTNEED, 3.2: UNKNOWN
- Status changed from Open to Closed
This was fixed in Ruby 3.3:
$ ruby -v -e 'def m(*); ->(*) { p(*) }; end; m(1).call(2)'
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-openbsd]
-e:1: anonymous rest parameter is also used within block
-e: compile error (SyntaxError)
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0Like1Like0Like0Like0