Project

General

Profile

Actions

Bug #19983

closed

Nested `*` seems incorrect

Added by Eregon (Benoit Daloze) about 1 year ago. Updated 10 months ago.

Status:
Closed
Assignee:
-
Target version:
-
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.


Related issues 1 (0 open1 closed)

Related to Ruby master - Feature #19370: Anonymous parameters for blocks?Closedmatz (Yukihiro Matsumoto)Actions
Actions #1

Updated by Eregon (Benoit Daloze) about 1 year ago

  • Description updated (diff)

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.

Actions #5

Updated by Eregon (Benoit Daloze) about 1 year ago

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.

Actions #10

Updated by nobu (Nobuyoshi Nakada) 12 months 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) 10 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)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like1Like0Like0Like0