Bug #20675
closedParse error with required kwargs and omitted parens
Description
As pointed out in https://github.com/mruby/mruby/issues/6268, keyword arguments without surrounding parens are a bit confusing, e.g.
def foo arg:
123
end
is parsed as
def foo(arg:)
123
end
where
k=25
f k:
10
is parserd as
k=25
f(k: 10)
In summary, should we ignore newlines after keyword labels? Should we make them behave consistent?
Matz.
Updated by bkuhlmann (Brooke Kuhlmann) 3 months ago
I think this would be great and would love to use keyword parameters without parenthesis...but I don't know how complicated this would be for the parser (including backwards compatibility which Jeremy (Evans) has mentioned before). If this were made possible -- there is an upside -- as anonymous blocks would also benefit from this support as this is not valid syntax (currently):
def demo positional, &block
other positional, &block
end
💡 For more on this, see Issue 18441.
Updated by Dan0042 (Daniel DeLorme) 3 months ago
I agree that f k:
at end of line should be parsed as f(k:)
. Even though it is backward incompatible, it can be detected statically, so the migration path is easy. Ruby 3.4 could output a deprecation warning at parse time. We could have a script/gem to detect if the pattern is currently used in any files, so people can check their application code. If it's used in any gems they could be flagged as incompatible with Ruby 3.5. There's a number of pain-free ways of dealing with this.
Updated by ko1 (Koichi Sasada) 3 months ago
This change is compatibility issue and I counted the number of def foo k:<newline>
patterns and I found about 4000 cases in recent gems.
https://gist.github.com/ko1/cd46d87c40df6896f2c885094133bf88
Updated by Dan0042 (Daniel DeLorme) 3 months ago
I believe Matz was talking about changing the behavior of f k:<newline>
, so method definition def foo k:<newline>
would remain the same.
Although f k:<newline>expr
would be incompatible, what about f(k:<newline>expr)
?
Updated by jeremyevans0 (Jeremy Evans) 3 months ago
The reason for this inconsistency is backwards compatibility, so as not to break existing code when omitted hash value support was added in Ruby 3.1.
There is historical precedence for breaking backwards compatibility for a very similar case. In this example:
def foo arg:
123
arg
end
foo
# Ruby < 2.0: SyntaxError
# Ruby 2.0: 123
# Ruby >= 2.1: ArgumentError, missing keyword: arg
There was no deprecation warning for the change in 2.1. I think if we want to change behavior for foo arg:<newline>value
from foo(arg: value)
to foo(arg:); value
, we should add a deprecation warning in 3.4, and then change the behavior in 3.5.
Updated by ko1 (Koichi Sasada) 3 months ago
Dan0042 (Daniel DeLorme) wrote in #note-4:
I believe Matz was talking about changing the behavior of
f k:<newline>
, so method definitiondef foo k:<newline>
would remain the same.Although
f k:<newline>expr
would be incompatible, what aboutf(k:<newline>expr)
?
for f k:<newline>val
, I found about 500 cases.
https://gist.github.com/ko1/e15fd4959675db07188e7a67ddc1c2c6
Updated by Dan0042 (Daniel DeLorme) 3 months ago
for
f k:<newline>val
, I found about 500 cases.
Thank you for searching. That's a lot more than I was able to find in my 950 sample gems, and with such a number I would vote to not change anything.
Updated by matz (Yukihiro Matsumoto) 3 months ago
- Status changed from Open to Closed
OK, I understand the reason and background of this behavior. The issue is withdrawn.
Matz.