From 5d5367ed00c22cc194b8a2411b2b4b828751003b Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 31 Aug 2022 23:30:53 +0900 Subject: update hugo --- .../ruby-then-keyword-and-case-in/index.html | 150 ++++++++++----------- 1 file changed, 75 insertions(+), 75 deletions(-) (limited to 'docs/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html') diff --git a/docs/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/docs/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index 2ef9f05..7d62273 100644 --- a/docs/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/docs/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -15,7 +15,7 @@ - + @@ -50,61 +50,61 @@

case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。

then とは

使われることは稀だが、Ruby では then がキーワードになっている。次のように使う:

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

このキーワードが現れうる場所はいくつかあり、ifunlessrescuecase 構文がそれに当たる。 +

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

このキーワードが現れうる場所はいくつかあり、ifunlessrescuecase 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。

-
# Example:
-
-if x then
-  a
-end
-
-unless x then
-  a
-end
-
-begin
-  a
-rescue then
-  b
-end
-
-case x
-when p then
-  a
-end
-

なぜ普段は書かなくてもよいのか

+
# Example:
+
+if x then
+  a
+end
+
+unless x then
+  a
+end
+
+begin
+  a
+rescue then
+  b
+end
+
+case x
+when p then
+  a
+end
+

なぜ普段は書かなくてもよいのか

普通 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
+
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
+20:1: syntax error, unexpected `end', expecting end-of-input
+...f true puts 'Hello, World!' end
 

二つ目のメッセージは無視して一つ目を読むと、then; か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。

ポイントは改行が then (や ;) の代わりとなることである。true の後に改行を入れてみる。

-
if true
-puts 'Hello, World!' end
-

無事 Hello, World! と出力されるようになった。

+
if true
+puts 'Hello, World!' end
+

無事 Hello, World! と出力されるようになった。

なぜ then; や改行が必要か

なぜ then; や改行 (以下 「then 等」) が必要なのだろうか。次の例を見てほしい:

-
if a b end
-

then; も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 +

if a b end
+

then; も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。

-
# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
-if a then
-  b
-end
-
# a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、
-# その結果が truthy なら何もしない
-if a(b) then
-end
-

then 等はこの曖昧性を排除するためにあり、条件式は if から 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 などの { も同じ役割を持つ。

Ruby の場合、プログラマーが書きやすいよう改行でもって then が代用できるので、ほとんどの場合 then は必要ない。

case - in における then

@@ -142,33 +142,33 @@ C系の if 後に来る (/) や、Python ;

ここで、keyword_in は文字通り inp_top_expr はいわゆるパターン、thenthen キーワードのことではなく、この記事で then 等と呼んでいるもの、つまり then キーワード、;、改行のいずれかである。

これにより、case - when による従来の構文と同じように、then 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:

-
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
-

ところで、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
-

まとめ

+
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
+

ところで、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
+

まとめ