[Ruby] then keyword and case in

TL; DR

In the pattern matching syntax with case -- in, you can use then as well as case -- when (you may need to use it).

What is then

Although rarely used, then is the keyword in Ruby. Use as follows:

if cond then
  puts "Y"
else
  puts "N"
end

There are several places where this keyword can appear, such as the if, unless, rescue, and case syntax. As mentioned above, after writing some condition, put then and it acts as a marker to indicate that the expression ends there.

# Example:

if x then
  a
end

unless x then
  a
end

begin
  a
rescue then
  b
end

case x
when p then
  a
end

Why you don't usually have to write

Normally, you don't write then in Ruby code. why. You can see it by running the following code.

if true puts 'Hello, World!' end

The following syntax error is output.

20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
if true puts 'Hello, World!' end
        ^~~~
20:1: syntax error, unexpected `end', expecting end-of-input
...f true puts 'Hello, World!' end

Ignoring the second message and reading the first one, it seems that an error occurs because then or; or a variable or a method appears where a line break should come.

The point is that line breaks replace then (or; ). Try inserting a line break after true.

if true
puts 'Hello, World!' end

Hello, World! Is now output safely.

Why then,; and line breaks are needed

Why do we need then,; and line breaks (hereinafter" then`, etc. ")? See the following example:

if a b end

There are no then,; , or line breaks, so an error occurs because you don't know how long the conditional expression continues. This example can be interpreted in two ways.

#If the evaluation result of the variable or method a is truthy, the variable or method b is evaluated.
if a then
  b
end
#Call the method a by passing the variable b or the evaluation result of the method to the method
#If the result is truthy, do nothing
if a(b) then
end

It is clarified that then etc. is to eliminate this ambiguity, and the conditional expression is between if and then etc. The (/) that comes after the C-type if, and the { such as the Python : and Rust/Go/Swift have the same role.

In the case of Ruby, then can be substituted with line breaks to make it easier for programmers to write, so in most cases then is not needed.

case -- then in in

I finally got to the main subject. The upcoming Ruby 3.0 will include pattern matching syntax using the case and in keywords. This syntax also requires then etc. as a delimiter from the pattern part. Since there is no formal grammar specification in (current) Ruby, I referred to the definition file of yacc (the explanation of yacc is omitted).

https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986

p_case_body	: keyword_in
		    {
			SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
			p->command_start = FALSE;
			$<ctxt>1 = p->ctxt;
			p->ctxt.in_kwarg = 1;
			$<tbl>$ = push_pvtbl(p);
		    }
		    {
			$<tbl>$ = push_pktbl(p);
		    }
		  p_top_expr then
		    {
			pop_pktbl(p, $<tbl>3);
			pop_pvtbl(p, $<tbl>2);
			p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
		    }
		  compstmt
		  p_cases
		    {
		    /*%%%*/
			$$ = NEW_IN($4, $7, $8, &@$);
		    /*% %*/
		    /*% ripper: in!($4, $7, escape_Qundef($8)) %*/
		    }
		;

Simplified version:

p_case_body	: keyword_in p_top_expr then compstmt p_cases
		;

Here, keyword_in is literally in, p_top_expr is the so-called pattern, then is not the then keyword, but what we call then etc. in this article, that is, the then keyword. , ;, One of the line breaks.

From this, it was found that then etc. should be inserted after the pattern in the same way as the conventional syntax of case -- when. In other words, it can be one of the following three ways:

case x
in 1 then a
in 2 then b
in 3 then c
end

case x
in 1
  a
in 2
  b
in 3
  c
end

case x
in 1; a
in 2; b
in 3; c
end

By the way, p_top_expr can have a guard clause by if, so in that case it looks similar to if-then.

case x
in 0 then a
in n if n < 0 then b
in n then c
end

Summary

Recommended Posts

[Ruby] then keyword and case in
Write keys and values in Ruby
Make bubble sort and selection sort in Ruby
Summary of hashes and symbols in Ruby
[Ruby] Classification and usage of loops in Ruby
Difference between "|| =" and "instance_variable_defined?" In Ruby memoization
Heavy in Ruby! ??
Ruby and Gem
Ruby if, case
[Understanding] Differences between hashes and arrays in Ruby
Put CSV files containing "'" and "" "in MySQL in Ruby 2.3
Just put `clang 12.0.0` in macOS` Catalina` and put `ruby 3.0.0`
[Ruby] Classes and instances
Symbols and Destructive Ruby
About eval in Ruby
[Ruby] Big Decimal and DECIMAL
Differences between Ruby syntax error statements in Ruby and binary
Display a loading image in JavaFX and then display another image
Ruby classes and instances
Ruby inheritance and delegation
[Ruby] Difficulty in refactoring logical operators (accuracy and readability)
Ruby variables and methods
Output triangle in Ruby
How to handle TSV files and CSV files in Ruby
Variable type in ruby
Fast popcount in Ruby
Handling of date and time in Ruby. Use Date and Time properly.
Math Girls Secret Note 104th implemented in Ruby and C
About the difference between "(double quotation)" and "single quotation" in Ruby
AtCoder dwango Programming Contest B in Ruby, Perl and Java
Handling of line beginning and line ending in regular expressions in Ruby
Write DiscordBot to Spreadsheets Write in Ruby and run with Docker
ABC177 --solving E in Ruby
Validate JWT token in Ruby
Implemented XPath 1.0 parser in Ruby
Read design patterns in Ruby
GraphQL Ruby and actual development
Write class inheritance in Ruby
Mock and stub in RSpec
Integer unified into Integer in Ruby 2.4
Multiplication in a Ruby array
About regular expressions in Ruby
About Ruby hashes and symbols
Ruby C extension and volatile
Summarize Ruby and Dependency Injection
Birthday attack calculation in Ruby
Judgment of fractions in Ruby
About Ruby and object model
Find Roman numerals in Ruby
Try using gRPC in Ruby
[Ruby] Singular methods and singular classes
About Ruby classes and instances
Ruby variables and functions (methods)
Ruby methods and classes (basic)
Creating Ruby classes and instances
[Ruby] Find numbers in arrays
NCk mod p in Ruby
Chinese Remainder Theorem in Ruby
[Ruby] Singular methods and singular classes
Create and integrate Slack App and AWS Lambda (for ruby) in 30 minutes
Install gem in Serverless Framework and AWS Lambda with Ruby environment