From 7f15e0b8277ac8b101b4f71ce57c1c5442927141 Mon Sep 17 00:00:00 2001
From: nsfisis
- この記事は Qiita から移植してきたものです。 元 URL:https://qiita.com/nsfisis/items/787a8cf888a304497223
+ この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223
- case-inによるパターンマッチング構文でも、case-whenと同じようにthenが使える (場合によっては使う必要がある)。
+ case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。
thenとはthen とは
- 使われることは稀だが、Ruby ではthenがキーワードになっている。次のように使う:
+ 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う:
if cond then
puts "Y"
else
puts "N"
end
-
+
- このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case構文がそれに当たる。 上記のように、何か条件を書いた後thenを置き、式がそこで終了していることを示すマーカーとして機能する。
+ このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。
# Example:
if x then
@@ -109,82 +109,82 @@ b
a
end
- 普通 Ruby のコードでthenを書くことはない。なぜか。次のコードを実行してみるとわかる。
+ 普通 Ruby のコードで then を書くことはない。なぜか。次のコードを実行してみるとわかる。
if true puts 'Hello, World!' end
-
+
次のような構文エラーが出力される。
- +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
-
+
- 二つ目のメッセージは無視して一つ目を読むと、thenか;か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。
+ 二つ目のメッセージは無視して一つ目を読むと、then か ; か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。
- ポイントは改行がthen(や;) の代わりとなることである。trueの後に改行を入れてみる。
+ ポイントは改行が then (や ;) の代わりとなることである。true の後に改行を入れてみる。
if true
puts 'Hello, World!' end
-
+
無事 Hello, World! と出力されるようになった。
thenや;や改行が必要かthen や ; や改行が必要か
- なぜthenや;や改行 (以下 「then等」) が必要なのだろうか。次の例を見てほしい:
+ なぜ then や ; や改行 (以下 「then 等」) が必要なのだろうか。次の例を見てほしい:
if a b end
-
+
- thenも;も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。
+ then も ; も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。
# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
if a then
b
end
-
+
# a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、
# その結果が truthy なら何もしない
if a(b) then
end
-
+
- then等はこの曖昧性を排除するためにあり、条件式はifからthen等までの間にある、ということを明確にする。 C系のif後に来る(/)や、Python の:、Rust/Go/Swift などの{も同じ役割を持つ。
+ then 等はこの曖昧性を排除するためにあり、条件式は if から then 等までの間にある、ということを明確にする。 C系の if 後に来る (/) や、Python の :、Rust/Go/Swift などの { も同じ役割を持つ。
- Ruby の場合、プログラマーが書きやすいよう改行でもってthenが代用できるので、ほとんどの場合thenは必要ない。
+ Ruby の場合、プログラマーが書きやすいよう改行でもって then が代用できるので、ほとんどの場合 then は必要ない。
case-inにおけるthencase - in における then
- ようやく本題にたどり着いた。来る Ruby 3.0 ではcaseとinキーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとしてthen等が必要になる。 (現在の) Ruby には formal な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc の説明は省略)。
+ ようやく本題にたどり着いた。来る Ruby 3.0 では case と in キーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとして then 等が必要になる。 (現在の) Ruby には formal な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc の説明は省略)。
https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986
- +p_case_body : keyword_in
{
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
@@ -211,22 +211,22 @@ b
/*% ripper: in!($4, $7, escape_Qundef($8)) %*/
}
;
-
+
簡略版:
- +p_case_body : keyword_in p_top_expr then compstmt p_cases
;
-
+
- ここで、keyword_inは文字通りin、p_top_exprはいわゆるパターン、thenはthenキーワードのことではなく、この記事でthen等と呼んでいるもの、つまりthenキーワード、;、改行のいずれかである。
+ ここで、keyword_in は文字通り in、p_top_expr はいわゆるパターン、then は then キーワードのことではなく、この記事で then 等と呼んでいるもの、つまり then キーワード、;、改行のいずれかである。
- これにより、case-whenによる従来の構文と同じように、then等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:
+ これにより、case - when による従来の構文と同じように、then 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:
case x
in 1 then a
in 2 then b
@@ -247,36 +247,36 @@ c
in 2; b
in 3; c
end
-
+
- ところで、p_top_exprにはifによる guard clause が書けるので、その場合はif-thenと似たような見た目になる。
+ ところで、p_top_expr には if による guard clause が書けるので、その場合は if - then と似たような見た目になる。
case x
in 0 then a
in n if n < 0 then b
in n then c
end
ifやcaseの条件の後ろにはthen、;、改行のいずれかが必要
+ if や case の条件の後ろには then、;、改行のいずれかが必要
case-inでもthen等が必要になる
+ 3.0 で入る予定の case - in でも then 等が必要になる
parse.yを直接読めばよい
+ Ruby の構文を正確に知るには (現状) parse.y を直接読めばよい