Bug #19983
closedNested `*` seems incorrect
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.
Updated by kddnewton (Kevin Newton) about 1 year ago
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)
Updated by zverok (Victor Shepelev) about 1 year ago
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)
Updated by Eregon (Benoit Daloze) about 1 year ago
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.
Updated by Eregon (Benoit Daloze) about 1 year ago
- Related to Feature #19370: Anonymous parameters for blocks? added
Updated by kddnewton (Kevin Newton) about 1 year ago
->(*) {}
being a syntax error would break backward compatibility, since ->(*) {}
has always been allowed. It's not different from ->(foo, *, bar) {}
.
Updated by Eregon (Benoit Daloze) about 1 year ago
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.
Updated by zverok (Victor Shepelev) about 1 year ago
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.
Updated by Eregon (Benoit Daloze) about 1 year ago
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.
Updated by nobu (Nobuyoshi Nakada) about 1 year ago
- 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
Updated by jeremyevans0 (Jeremy Evans) 11 months ago
- 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)