aboutsummaryrefslogtreecommitdiffhomepage
path: root/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
diff options
context:
space:
mode:
Diffstat (limited to 'content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml')
-rw-r--r--content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml80
1 files changed, 40 insertions, 40 deletions
diff --git a/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml b/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
index 00afc01..64851fc 100644
--- a/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
+++ b/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml
@@ -16,26 +16,26 @@
</revision>
</revhistory>
</info>
- <simpara>
+ <para>
この記事は Qiita から移植してきたものです。 元 URL:
<link xl:href="https://qiita.com/nsfisis/items/787a8cf888a304497223">https://qiita.com/nsfisis/items/787a8cf888a304497223</link>
- </simpara>
- <simpara>
+ </para>
+ <para>
<hr/>
- </simpara>
+ </para>
<section xml:id="tl-dr">
<title>TL; DR</title>
- <simpara>
+ <para>
<literal>case</literal> - <literal>in</literal> によるパターンマッチング構文でも、<literal>case</literal> - <literal>when</literal>
と同じように <literal>then</literal> が使える (場合によっては使う必要がある)。
- </simpara>
+ </para>
</section>
<section xml:id="what-is-then-keyword">
<title><literal>then</literal> とは</title>
- <simpara>
+ <para>
使われることは稀だが、Ruby では <literal>then</literal>
がキーワードになっている。次のように使う:
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
if cond then
@@ -45,11 +45,11 @@
end
]]>
</programlisting>
- <simpara>
+ <para>
このキーワードが現れうる場所はいくつかあり、<literal>if</literal>、<literal>unless</literal>、<literal>rescue</literal>、<literal>case</literal>
構文がそれに当たる。 上記のように、何か条件を書いた後 <literal>then</literal>
を置き、式がそこで終了していることを示すマーカーとして機能する。
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
# Example:
@@ -77,18 +77,18 @@
</section>
<section xml:id="why-then-is-usually-unnecessary">
<title>なぜ普段は書かなくてもよいのか</title>
- <simpara>
+ <para>
普通 Ruby のコードで <literal>then</literal>
を書くことはない。なぜか。次のコードを実行してみるとわかる。
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
if true puts 'Hello, World!' end
]]>
</programlisting>
- <simpara>
+ <para>
次のような構文エラーが出力される。
- </simpara>
+ </para>
<literallayout class="monospaced">
<![CDATA[
20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
@@ -98,40 +98,40 @@
...f true puts 'Hello, World!' end
]]>
</literallayout>
- <simpara>
+ <para>
二つ目のメッセージは無視して一つ目を読むと、<literal>then</literal> か <literal>;</literal>
か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。
- </simpara>
- <simpara>
+ </para>
+ <para>
ポイントは改行が <literal>then</literal> (や <literal>;</literal>) の代わりとなることである。<literal>true</literal>
の後に改行を入れてみる。
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
if true
puts 'Hello, World!' end
]]>
</programlisting>
- <simpara>
+ <para>
無事 Hello, World! と出力されるようになった。
- </simpara>
+ </para>
</section>
<section xml:id="why-then-or-linebreak-is-needed">
<title>なぜ <literal>then</literal> や <literal>;</literal> や改行が必要か</title>
- <simpara>
+ <para>
なぜ <literal>then</literal> や <literal>;</literal> や改行 (以下 「<literal>then</literal> 等」)
が必要なのだろうか。次の例を見てほしい:
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
if a b end
]]>
</programlisting>
- <simpara>
+ <para>
<literal>then</literal> も <literal>;</literal>
も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。
この例は二通りに解釈できる。
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
@@ -148,28 +148,28 @@
end
]]>
</programlisting>
- <simpara>
+ <para>
<literal>then</literal> 等はこの曖昧性を排除するためにあり、条件式は <literal>if</literal> から <literal>then</literal>
等までの間にある、ということを明確にする。 C系の <literal>if</literal> 後に来る <literal>(</literal>/<literal>)</literal>
や、Python の <literal>:</literal>、Rust/Go/Swift などの <literal>{</literal> も同じ役割を持つ。
- </simpara>
- <simpara>
+ </para>
+ <para>
Ruby の場合、プログラマーが書きやすいよう改行でもって <literal>then</literal>
が代用できるので、ほとんどの場合 <literal>then</literal> は必要ない。
- </simpara>
+ </para>
</section>
<section xml:id="then-in-case-in">
<title><literal>case</literal> - <literal>in</literal> における <literal>then</literal></title>
- <simpara>
+ <para>
ようやく本題にたどり着いた。来る Ruby 3.0 では <literal>case</literal> と <literal>in</literal>
キーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとして
<literal>then</literal> 等が必要になる。 (現在の) Ruby には formal
な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc
の説明は省略)。
- </simpara>
- <simpara>
+ </para>
+ <para>
<link xl:href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</link>
- </simpara>
+ </para>
<programlisting language="yacc" linenumbering="unnumbered">
<![CDATA[
p_case_body : keyword_in
@@ -200,25 +200,25 @@
;
]]>
</programlisting>
- <simpara>
+ <para>
簡略版:
- </simpara>
+ </para>
<programlisting language="yacc" linenumbering="unnumbered">
<![CDATA[
p_case_body : keyword_in p_top_expr then compstmt p_cases
;
]]>
</programlisting>
- <simpara>
+ <para>
ここで、<literal>keyword_in</literal> は文字通り <literal>in</literal>、<literal>p_top_expr</literal>
はいわゆるパターン、<literal>then</literal> は <literal>then</literal>
キーワードのことではなく、この記事で <literal>then</literal> 等と呼んでいるもの、つまり
<literal>then</literal> キーワード、<literal>;</literal>、改行のいずれかである。
- </simpara>
- <simpara>
+ </para>
+ <para>
これにより、<literal>case</literal> - <literal>when</literal> による従来の構文と同じように、<literal>then</literal>
等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
case x
@@ -243,10 +243,10 @@
end
]]>
</programlisting>
- <simpara>
+ <para>
ところで、<literal>p_top_expr</literal> には <literal>if</literal> による guard clause
が書けるので、その場合は <literal>if</literal> - <literal>then</literal> と似たような見た目になる。
- </simpara>
+ </para>
<programlisting language="ruby" linenumbering="unnumbered">
<![CDATA[
case x