Bug #19033
closedOne-liner pattern match as Boolean arg syntax error
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) about 2 years 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) about 2 years 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.
Updated by duerst (Martin Dürst) about 2 years 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 forexpect(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 asexpect(value) in pattern
, not asexpect(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 years 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 2 years 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 2 years 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 2 years ago
mame (Yusuke Endoh) wrote in #note-6:
Note that
foo(1, 2, 3 in ary)
could be inherently ambiguous. It can be interpreted asfoo((1, 2, 3 in ary))
orfoo(1, 2, (3 in ary))
.
Agreed, these are difficult edge cases, and trying to make the parser work with them would be challenging.