Project

General

Profile

Actions

Bug #20675

closed

Parse error with required kwargs and omitted parens

Added by matz (Yukihiro Matsumoto) 3 months ago. Updated 3 months ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-dev:<unknown>]

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.

Actions #1

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.

Actions #2

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.

Actions #3

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

Actions #4

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) ?

Actions #5

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.

Actions #6

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 definition def foo k:<newline> would remain the same.

Although f k:<newline>expr would be incompatible, what about f(k:<newline>expr) ?

for f k:<newline>val, I found about 500 cases.

https://gist.github.com/ko1/e15fd4959675db07188e7a67ddc1c2c6

Actions #7

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.

Actions #8

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.

Actions

Also available in: Atom PDF

Like1
Like0Like1Like0Like0Like1Like0Like0Like0