Bug #17925
openPattern matching syntax using semicolon one-line
Description
Summary¶
There are the following differences between case ... when
and case ... in
. Is this an expected behavior?
% ruby -v
ruby 3.1.0dev (2021-05-28T16:34:27Z master e56ba6231f) [x86_64-darwin19]
% ruby -ce 'case expression when 42; end'
Syntax OK
% ruby -ce 'case expression in 42; end'
-e:1: warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!
-e:1: syntax error, unexpected `end', expecting `when'
case expression in 42; end
So, I have two concerns.
- Since the pattern matching syntax is different from
case ... when
, can't user write semicolon one-linecase ... in
in the same semicolon one-line ascase ... when
? - Does
case expression in 42; end
display an experimental warning of one-line pattern matching. Right?
This is reproduced in Ruby 3.1.0-dev and Ruby 3.0.1.
Additional Information¶
NOTE 1: I understand that only syntax that doesn't use case
and end
is experimental one-line pattern matching syntax.
% ruby -ce 'expression in 42'
-e:1: warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!
Syntax OK
NOTE 2: The syntax is OK if a semicolon is used between expression
and in
. But case ... when
is a valid syntax to omit.
% ruby -e ruby -ce 'case expression; in 42; end'
Syntax OK
Updated by koic (Koichi ITO) over 3 years ago
NOTE 1: I understand that only syntax that doesn't use case and end is experimental one-line pattern matching syntax.
A little supplement. The following is also an experimental one-line pattern matching syntax since Ruby 3.0, but the =>
one-line pattern matching syntax is no problem.
% ruby -e "'' => ''"
-e:1: warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!
Updated by nobu (Nobuyoshi Nakada) over 3 years ago
It is a known restriction that the code is parsed as case (expression in 42)
.
Let me consider if it is possible to make that a priority.
Updated by jeremyevans0 (Jeremy Evans) about 1 year ago
@kddnewton (Kevin Newton) Is this possible to fix in YARP?
@yui-knk (Kaneko Yuichiro) Is this possible to fix in parse.y/lrama?
Updated by nobu (Nobuyoshi Nakada) about 1 year ago
I thought it a trade-off.
To allow the statement, one-line pattern matching is not allowed there.
But it returns true
/false
only and may be useless for case
.
Updated by kddnewton (Kevin Newton) about 1 year ago
This is interesting. It surfaces an incompatibility we have. I didn't realize Ruby didn't allow this, so YARP allows case expression in 42; end
to parse as expected by the OP here. If parse.y
can't support this, I will need to explicitly disallow this in YARP.
Updated by yui-knk (Kaneko Yuichiro) about 1 year ago
It's possible https://github.com/yui-knk/ruby/tree/bugs_17925.
I think this is not limitaion but the matter of choice. Currently expr
is expected after case
therefore expression in 42
is interpreted as expr
.
For example
case expression in 42
in true
in false
end
Before the change, this is interpreted as
case (expression in 42)
in true
in false
end
After the change, this is interpreted as
case expression
in 42
in true
in false
end
Impact¶
For case ... in
As shown above, this will change the behavior of current codes.
Before:
expression = 42
case expression in 42
in true
p :t
in false
p :f
end
#=> :t
expression = 421
case expression in 42
in true
p :t
in false
p :f
end
#=> :f
After:
expression = 42
case expression in 42
in true
p :t
in false
p :f
end
#=> nothing printed, because body for 42 is empty
expression = 421
case expression in 42
in true
p :t
in false
p :f
end
#=> 421 (NoMatchingPatternError)
# because nothing matches
For case ... when
Before this change, this is valid
case expression in 42
when true
p :t
when false
p :f
end
However after this change, it's invalid
case expression in 42
when true
p :t
when false
p :f
end
# test2.rb:2: syntax error, unexpected `when' (SyntaxError)
# when true
# ^~~~
Impact on case ... when
is inevitable because new grammar recognizes this is case ... in
when third symbol (in
) appears.
New exception¶
expr
appears other place of the grammar. For example, if expr ...
, while expr ...
and so on. This change introduces an exception that you can write one line pattern matching after if
, unless
, while
, until
and so on but you can't after case
.
Conclusion¶
- This a matter of choice not limitaion
- New grammar introduces incompatibility. It changes the behavior of
case ... in
and breakscase ... when
- It introduces an exceptional rule to the grammar
- As a reporter says, there is workaround to add
;
afterexpression
expression in 42
always returns true
or false
therefore it might be useless for case
. Howerver we need to consider such impacts and benefits before decision making.
Note¶
Impact on case ... when
can be found as Shift/Reduce conflict. In this state, shift derives case ... when
, on the other hand reduce derives case ... in
.
https://github.com/yui-knk/ruby/tree/bugs_17925_2
State 394
shift/reduce conflict on token "`in'":
60 expr0: arg •
71 expr: arg • "`in'" @7 @8 p_top_expr_body
First example: $@1 k_case arg • "`in'" @7 @8 p_top_expr_body opt_terms @19 case_body k_end "=>" @5 @6 p_top_expr_body opt_terms
Shift derivation
program
↳ 2: $@1 top_compstmt
↳ 3: top_stmts opt_terms
↳ 5: top_stmt
↳ 7: stmt
↳ 37: expr
↳ 68: arg "=>" @5 @6 p_top_expr_body
↳ 269: primary
↳ 358: k_case expr_value opt_terms @19 case_body k_end
↳ 78: expr
↳ 71: arg • "`in'" @7 @8 p_top_expr_body
Second example: $@1 k_case arg • opt_terms "`in'" @38 @39 p_top_expr then $@40 compstmt p_cases k_end '[' opt_call_args rbracket "operator-assignment" lex_ctxt command_rhs opt_terms "end-of-input"
Reduce derivation
$accept
↳ 0: program "end-of-input"
↳ 2: $@1 top_compstmt
↳ 3: top_stmts opt_terms
↳ 5: top_stmt
↳ 7: stmt
↳ 32: command_asgn
↳ 41: primary_value '[' opt_call_args rbracket "operator-assignment" lex_ctxt command_rhs
↳ 377: primary
↳ 361: k_case expr_value0 opt_terms p_case_body k_end
↳ 77: expr0 ↳ 500: "`in'" @38 @39 p_top_expr then $@40 compstmt p_cases
↳ 60: arg •
Updated by kddnewton (Kevin Newton) about 1 year ago
I agree with @yui-knk (Kaneko Yuichiro) here, I think this is definitely a choice and at this point can't be changed.