Project

General

Profile

Actions

Bug #19033

closed

One-liner pattern match as Boolean arg syntax error

Added by baweaver (Brandon Weaver) 2 months ago. Updated about 1 month ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:110154]

Description

I was chatting earlier with Seb Wilgosz about pattern matching in tests, and suggested that he might consider the following:

expect result in pattern

...but he reported back this will syntax error, including with parens:

res = [:not_found, 999]
expect(res in [:not_found, *payload])
# => SyntaxError:
# /spec/app/interactors/articles/publish_spec.rb:13: syntax error, unexpected `in', expecting ')'

Interestingly though the following work:

res = [:not_found, 999]

expect(res) in([:not_found, *payload])
# 1 example, 0 failures
expect(res) in([:not_found, 1, 3])
# 1 example, 0 failures

While this appears like an RSpec issue I would contend that it is reproducible with any other method that takes a boolean-like argument.

For me this feels like a syntax bug, but could see a case where it may be interpreted as ambiguous depending on the precedence of in relative to method arguments much like method_name value if condition is vague between method_name(value) if condition and method_name(value if condition). That'll be especially difficult if it's method_name value in pattern if condition, so I do not envy parser writers here.

Would be curious for thoughts on that, or if we're looking at that wrong.

Updated by baweaver (Brandon Weaver) 2 months ago

Addendum: We did find that expect((value in pattern)) works, but not expect(value in pattern), which is where we find things to be confusing

Updated by jeremyevans0 (Jeremy Evans) 2 months ago

Regarding expect(value in pattern), I think it is expected that is a syntax error. This is how Ruby has always worked for expect(true if true), which is invalid syntax (expect((true if true)) is valid syntax).

In regards to expect value in pattern, the syntax is a ambiguous. I would assume if it was supported at all, it would be parsed as expect(value) in pattern, not as expect(value in pattern). I think it's best for it to remain a syntax error.

Actions #3

Updated by duerst (Martin Dürst) 2 months ago

jeremyevans0 (Jeremy Evans) wrote in #note-2:

Regarding expect(value in pattern), I think it is expected that is a syntax error. This is how Ruby has always worked for expect(true if true), which is invalid syntax (expect((true if true)) is valid syntax).

It's fine to know that this is as it was. But is there a deeper reason for it? For example, would expect(value in pattern) be ambiguous in any way? Or is it too difficult to get the parser to accept it? I'm asking because it looks very counterintuitive to me that A(B) be invalid, but A((B)) valid. If possible, I think we should make it valid.

In regards to expect value in pattern, the syntax is a ambiguous. I would assume if it was supported at all, it would be parsed as expect(value) in pattern, not as expect(value in pattern). I think it's best for it to remain a syntax error.

I agree that making the programmer disambiguate is the right thing to do.

Updated by Dan0042 (Daniel DeLorme) about 2 months ago

expect value in pattern is a syntax error, but
expect value if pattern is parsed as expect(value) if pattern
I wonder why the difference?

Updated by matz (Yukihiro Matsumoto) about 1 month ago

  • Status changed from Open to Rejected

I can understand the feeling the a in b should be accepted as an argument expression. But in reality, it needs huge effort to modify the parser.
I don't think it worth both cost and complexity. If someone comes up with the pull-request, we will reconsider.

Matz.

Updated by mame (Yusuke Endoh) about 1 month ago

Note that foo(1, 2, 3 in ary) could be inherently ambiguous. It can be interpreted as foo((1, 2, 3 in ary)) or foo(1, 2, (3 in ary)).

Updated by baweaver (Brandon Weaver) about 1 month ago

mame (Yusuke Endoh) wrote in #note-6:

Note that foo(1, 2, 3 in ary) could be inherently ambiguous. It can be interpreted as foo((1, 2, 3 in ary)) or foo(1, 2, (3 in ary)).

Agreed, these are difficult edge cases, and trying to make the parser work with them would be challenging.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0