aboutsummaryrefslogtreecommitdiffhomepage
path: root/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-01 00:49:15 +0900
committernsfisis <nsfisis@gmail.com>2026-02-01 00:49:19 +0900
commit6dedddc545e2f1930bdc2256784eb1551bd4231d (patch)
tree75fcb5a6043dc0f2c31b098bf3cfd17a2b938599 /services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
parentd08e3edb65b215152aa26e3518fb2f2cd7071c4b (diff)
downloadnsfisis.dev-6dedddc545e2f1930bdc2256784eb1551bd4231d.tar.gz
nsfisis.dev-6dedddc545e2f1930bdc2256784eb1551bd4231d.tar.zst
nsfisis.dev-6dedddc545e2f1930bdc2256784eb1551bd4231d.zip
feat(nuldoc): rewrite nuldoc in Ruby
Diffstat (limited to 'services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html')
-rw-r--r--services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html202
1 files changed, 107 insertions, 95 deletions
diff --git a/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
index 9035fa18..0592f0a6 100644
--- a/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
+++ b/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html
@@ -103,36 +103,38 @@
使われることは稀だが、Ruby では <code>then</code> がキーワードになっている。次のように使う:
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> cond </span><span style="color:#D73A49">then</span></span>
-<span class="line"><span style="color:#005CC5"> puts</span><span style="color:#032F62"> "Y"</span></span>
-<span class="line"><span style="color:#D73A49">else</span></span>
-<span class="line"><span style="color:#005CC5"> puts</span><span style="color:#032F62"> "N"</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">cond</span> <span style="color: #cf222e">then</span>
+ <span style="color: #953800">puts</span> <span style="color: #0a3069">"Y"</span>
+<span style="color: #cf222e">else</span>
+ <span style="color: #953800">puts</span> <span style="color: #0a3069">"N"</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
<p>
このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code> 構文がそれに当たる。 上記のように、何か条件を書いた後 <code>then</code> を置き、式がそこで終了していることを示すマーカーとして機能する。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># Example:</span></span>
-<span class="line"></span>
-<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> x </span><span style="color:#D73A49">then</span></span>
-<span class="line"><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span>
-<span class="line"></span>
-<span class="line"><span style="color:#D73A49">unless</span><span style="color:#24292E"> x </span><span style="color:#D73A49">then</span></span>
-<span class="line"><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span>
-<span class="line"></span>
-<span class="line"><span style="color:#D73A49">begin</span></span>
-<span class="line"><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">rescue</span><span style="color:#D73A49"> then</span></span>
-<span class="line"><span style="color:#24292E"> b</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span>
-<span class="line"></span>
-<span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span>
-<span class="line"><span style="color:#D73A49">when</span><span style="color:#005CC5"> p</span><span style="color:#D73A49"> then</span></span>
-<span class="line"><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781"># Example:</span>
+
+<span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">x</span> <span style="color: #cf222e">then</span>
+ <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">end</span>
+
+<span style="color: #cf222e">unless</span> <span style="color: #24292f;background-color: #f6f8fa">x</span> <span style="color: #cf222e">then</span>
+ <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">end</span>
+
+<span style="color: #cf222e">begin</span>
+ <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">rescue</span> <span style="color: #cf222e">then</span>
+ <span style="color: #24292f;background-color: #f6f8fa">b</span>
+<span style="color: #cf222e">end</span>
+
+<span style="color: #cf222e">case</span> <span style="color: #24292f;background-color: #f6f8fa">x</span>
+<span style="color: #cf222e">when</span> <span style="color: #953800">p</span> <span style="color: #cf222e">then</span>
+ <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
</section>
<section id="section--why-then-is-usually-unnecessary">
@@ -141,17 +143,19 @@
普通 Ruby のコードで <code>then</code> を書くことはない。なぜか。次のコードを実行してみるとわかる。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#005CC5"> true</span><span style="color:#005CC5"> puts</span><span style="color:#032F62"> 'Hello, World!'</span><span style="color:#D73A49"> end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">if</span> <span style="color: #cf222e">true</span> <span style="color: #953800">puts</span> <span style="color: #0a3069">'Hello, World!'</span> <span style="color: #cf222e">end</span>
+</code></pre>
</div>
<p>
次のような構文エラーが出力される。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'</span></span>
-<span class="line"><span>if true puts 'Hello, World!' end</span></span>
-<span class="line"><span> ^~~~</span></span>
-<span class="line"><span>20:1: syntax error, unexpected `end', expecting end-of-input</span></span>
-<span class="line"><span>...f true puts 'Hello, World!' end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><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>
</div>
<p>
二つ目のメッセージは無視して一つ目を読むと、<code>then</code> か <code>;</code> か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。
@@ -160,8 +164,9 @@
ポイントは改行が <code>then</code> (や <code>;</code>) の代わりとなることである。<code>true</code> の後に改行を入れてみる。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#005CC5"> true</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#032F62"> 'Hello, World!'</span><span style="color:#D73A49"> end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">if</span> <span style="color: #cf222e">true</span>
+<span style="color: #953800">puts</span> <span style="color: #0a3069">'Hello, World!'</span> <span style="color: #cf222e">end</span>
+</code></pre>
</div>
<p>
無事 Hello, World! と出力されるようになった。
@@ -173,22 +178,25 @@
なぜ <code>then</code> や <code>;</code> や改行 (以下 「<code>then</code> 等」) が必要なのだろうか。次の例を見てほしい:
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> a b </span><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">a</span> <span style="color: #24292f;background-color: #f6f8fa">b</span> <span style="color: #cf222e">end</span>
+</code></pre>
</div>
<p>
<code>then</code> も <code>;</code> も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。この例は二通りに解釈できる。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span></span>
-<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> a </span><span style="color:#D73A49">then</span></span>
-<span class="line"><span style="color:#24292E">b</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span>
+<span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">a</span> <span style="color: #cf222e">then</span>
+<span style="color: #24292f;background-color: #f6f8fa">b</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span></span>
-<span class="line"><span style="color:#6A737D"># その結果が truthy なら何もしない</span></span>
-<span class="line"><span style="color:#D73A49">if</span><span style="color:#6F42C1"> a</span><span style="color:#24292E">(b) </span><span style="color:#D73A49">then</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span>
+<span style="color: #6e7781"># その結果が truthy なら何もしない</span>
+<span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">a</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">)</span> <span style="color: #cf222e">then</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
<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> も同じ役割を持つ。
@@ -209,39 +217,41 @@
<div class="filename">
parse.y
</div>
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>p_case_body : keyword_in</span></span>
-<span class="line"><span>{</span></span>
-<span class="line"><span> SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);</span></span>
-<span class="line"><span> p->command_start = FALSE;</span></span>
-<span class="line"><span> $&#x3C;ctxt>1 = p->ctxt;</span></span>
-<span class="line"><span> p->ctxt.in_kwarg = 1;</span></span>
-<span class="line"><span> $&#x3C;tbl>$ = push_pvtbl(p);</span></span>
-<span class="line"><span>}</span></span>
-<span class="line"><span>{</span></span>
-<span class="line"><span> $&#x3C;tbl>$ = push_pktbl(p);</span></span>
-<span class="line"><span>}</span></span>
-<span class="line"><span>p_top_expr then</span></span>
-<span class="line"><span>{</span></span>
-<span class="line"><span> pop_pktbl(p, $&#x3C;tbl>3);</span></span>
-<span class="line"><span> pop_pvtbl(p, $&#x3C;tbl>2);</span></span>
-<span class="line"><span> p->ctxt.in_kwarg = $&#x3C;ctxt>1.in_kwarg;</span></span>
-<span class="line"><span>}</span></span>
-<span class="line"><span>compstmt</span></span>
-<span class="line"><span>p_cases</span></span>
-<span class="line"><span>{</span></span>
-<span class="line"><span> /*%%%*/</span></span>
-<span class="line"><span> $$ = NEW_IN($4, $7, $8, &#x26;@$);</span></span>
-<span class="line"><span> /*% %*/</span></span>
-<span class="line"><span> /*% ripper: in!($4, $7, escape_Qundef($8)) %*/</span></span>
-<span class="line"><span>}</span></span>
-<span class="line"><span>;</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code>p_case_body : keyword_in
+{
+ SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
+ p-&gt;command_start = FALSE;
+ $&lt;ctxt&gt;1 = p-&gt;ctxt;
+ p-&gt;ctxt.in_kwarg = 1;
+ $&lt;tbl&gt;$ = push_pvtbl(p);
+}
+{
+ $&lt;tbl&gt;$ = push_pktbl(p);
+}
+p_top_expr then
+{
+ pop_pktbl(p, $&lt;tbl&gt;3);
+ pop_pvtbl(p, $&lt;tbl&gt;2);
+ p-&gt;ctxt.in_kwarg = $&lt;ctxt&gt;1.in_kwarg;
+}
+compstmt
+p_cases
+{
+ /*%%%*/
+ $$ = NEW_IN($4, $7, $8, &amp;@$);
+ /*% %*/
+ /*% ripper: in!($4, $7, escape_Qundef($8)) %*/
+}
+;
+</code></pre>
</div>
<p>
簡略版:
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>p_case_body : keyword_in p_top_expr then compstmt p_cases</span></span>
-<span class="line"><span>;</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code>p_case_body : keyword_in p_top_expr then compstmt p_cases
+;
+</code></pre>
</div>
<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>、改行のいずれかである。
@@ -250,36 +260,38 @@
これにより、<code>case</code> - <code>when</code> による従来の構文と同じように、<code>then</code> 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> b</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> c</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span>
-<span class="line"></span>
-<span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 1</span></span>
-<span class="line"><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 2</span></span>
-<span class="line"><span style="color:#24292E"> b</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 3</span></span>
-<span class="line"><span style="color:#24292E"> c</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span>
-<span class="line"></span>
-<span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">; a</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 2</span><span style="color:#24292E">; b</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 3</span><span style="color:#24292E">; c</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">case</span> <span style="color: #24292f;background-color: #f6f8fa">x</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">1</span> <span style="color: #cf222e">then</span> <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">2</span> <span style="color: #cf222e">then</span> <span style="color: #24292f;background-color: #f6f8fa">b</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">3</span> <span style="color: #cf222e">then</span> <span style="color: #24292f;background-color: #f6f8fa">c</span>
+<span style="color: #cf222e">end</span>
+
+<span style="color: #cf222e">case</span> <span style="color: #24292f;background-color: #f6f8fa">x</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">1</span>
+ <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">2</span>
+ <span style="color: #24292f;background-color: #f6f8fa">b</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">3</span>
+ <span style="color: #24292f;background-color: #f6f8fa">c</span>
+<span style="color: #cf222e">end</span>
+
+<span style="color: #cf222e">case</span> <span style="color: #24292f;background-color: #f6f8fa">x</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">1</span><span style="color: #24292f;background-color: #f6f8fa">;</span> <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">2</span><span style="color: #24292f;background-color: #f6f8fa">;</span> <span style="color: #24292f;background-color: #f6f8fa">b</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">3</span><span style="color: #24292f;background-color: #f6f8fa">;</span> <span style="color: #24292f;background-color: #f6f8fa">c</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
<p>
ところで、<code>p_top_expr</code> には <code>if</code> による guard clause が書けるので、その場合は <code>if</code> - <code>then</code> と似たような見た目になる。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> a</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#24292E"> n </span><span style="color:#D73A49">if</span><span style="color:#24292E"> n </span><span style="color:#D73A49">&#x3C;</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> b</span></span>
-<span class="line"><span style="color:#D73A49">in</span><span style="color:#24292E"> n </span><span style="color:#D73A49">then</span><span style="color:#24292E"> c</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">case</span> <span style="color: #24292f;background-color: #f6f8fa">x</span>
+<span style="color: #cf222e">in</span> <span style="color: #0550ae">0</span> <span style="color: #cf222e">then</span> <span style="color: #24292f;background-color: #f6f8fa">a</span>
+<span style="color: #cf222e">in</span> <span style="color: #24292f;background-color: #f6f8fa">n</span> <span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">n</span> <span style="color: #0550ae">&lt;</span> <span style="color: #0550ae">0</span> <span style="color: #cf222e">then</span> <span style="color: #24292f;background-color: #f6f8fa">b</span>
+<span style="color: #cf222e">in</span> <span style="color: #24292f;background-color: #f6f8fa">n</span> <span style="color: #cf222e">then</span> <span style="color: #24292f;background-color: #f6f8fa">c</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
</section>
<section id="section--outro">