Project

General

Profile

Actions

Feature #19134

open

** is not allowed in def foo(...)

Added by shugo (Shugo Maeda) 22 days ago. Updated 4 days ago.

Status:
Open
Priority:
Normal
Target version:
-
[ruby-dev:51203]

Description

* and & are allowed in the body of a method with ... argument forwarding, but ** is not allowed.

def foo(...)
  bar(*) # OK
  baz(&) # OK
  quux(**) # NG
end

Is it intended behavior?

It seems that parse.y has code like #ifdef RUBY3_KEYWORDS, and if RUBY3_KEYWORDS, ** will also be supported.


Related issues 1 (1 open0 closed)

Related to Ruby master - Bug #19165: Method (with no param) delegation with *, **, and ... is slowOpenActions

Updated by shugo (Shugo Maeda) 11 days ago

I've created a pull request: https://github.com/ruby/ruby/pull/6818

With this change a test of rbs.gem fails because argument types of def foo(...) is changed to (*untyped, **untyped **) from (*untyped), but I believe it's right.
(however, the specifal variable name ** should be hidden by rbs.gem.)
I've created a issue: https://github.com/ruby/rbs/issues/1163

Updated by matz (Yukihiro Matsumoto) 10 days ago

LGTM.

Matz.

Actions #3

Updated by shugo (Shugo Maeda) 10 days ago

  • Status changed from Open to Closed

Applied in changeset git|4fc668a4f3b9b67cc7566096ab55cab34c67c158.


Allow ** in def foo(...)

[Feature #19134]

Updated by shugo (Shugo Maeda) 10 days ago

matz (Yukihiro Matsumoto) wrote in #note-2:

LGTM.

Thank you. I've merged it.

I realized that my fix also chaged the behavior of the following code:

def foo(*, **, &)
  bar(...)
end

def bar(*args, **kw, &block)
  p [args, kw, block&.call]
end

foo(1, 2, x: 3, y: 4) { 5 }

My fix changed the result from [[1, 2], {}, 5] to [[1, 2], {:x=>3, :y=>4}, 5].
So ... is now a syntax sugar of *, **, &.

Updated by Eregon (Benoit Daloze) 4 days ago

IMHO if ... is used then *, ** and & should all be forbidden (a SyntaxError at parse time).
Because that way is the best for optimizing delegation.
And also taking apart * and ** is arguably not really delegation anymore.

Actions #6

Updated by Eregon (Benoit Daloze) 4 days ago

  • Related to Bug #19165: Method (with no param) delegation with *, **, and ... is slow added

Updated by Eregon (Benoit Daloze) 4 days ago

Although, it should still be possible to optimize delegation as good as possible and allow */**/& by having those behave like def args(*,**,&) = *, def kwargs(*,**,&) = **, def block(*,**,&) = & and as if * was replaced by args(...), etc, but that's of course at the expense of making the handling of those slightly slower and more complicated (but at least it doesn't slow down delegation via (...)).

Updated by shugo (Shugo Maeda) 4 days ago

Eregon (Benoit Daloze) wrote in #note-5:

IMHO if ... is used then *, ** and & should all be forbidden (a SyntaxError at parse time).
Because that way is the best for optimizing delegation.
And also taking apart * and ** is arguably not really delegation anymore.

& is allowed in 3.1, so it's a breaking change to prohibit it.

Updated by shugo (Shugo Maeda) 4 days ago

  • Status changed from Closed to Open

I think it's most conservative to probhibit * and **:

def foo(...)
  bar(&) # OK
  baz(*) # error
  quux(**) # error
end

And an error should occur in the following code instead of dropping keyword arguments:

def foo(*, **, &)
  bar(...)
end

def bar(*args, **kw, &block)
  p [args, kw, block&.call]
end

foo(1, 2, x: 3, y: 4) { 5 }

What do you think, Matz?

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0