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