diff options
Diffstat (limited to 'vhosts/blog/public/posts/2021-10-02')
7 files changed, 351 insertions, 290 deletions
diff --git a/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html b/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html index b6baad39..d99fc02c 100644 --- a/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html +++ b/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【C++】 属性構文の属性名にはキーワードが使える|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -74,25 +73,27 @@ タイトル落ち。まずはこのコードを見て欲しい。 </p> - <pre class="highlight" language="cpp"><code class="highlight"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><iostream></span></span> - -[[<span class="hljs-keyword">alignas</span>]] [[<span class="hljs-keyword">alignof</span>]] [[<span class="hljs-keyword">and</span>]] [[<span class="hljs-keyword">and_eq</span>]] [[<span class="hljs-keyword">asm</span>]] [[<span class="hljs-keyword">auto</span>]] [[<span class="hljs-keyword">bitand</span>]] -[[<span class="hljs-keyword">bitor</span>]] [[<span class="hljs-type">bool</span>]] [[<span class="hljs-keyword">break</span>]] [[<span class="hljs-keyword">case</span>]] [[<span class="hljs-keyword">catch</span>]] [[<span class="hljs-type">char</span>]] [[<span class="hljs-type">char16_t</span>]] -[[<span class="hljs-type">char32_t</span>]] [[<span class="hljs-keyword">class</span>]] [[<span class="hljs-keyword">compl</span>]] [[<span class="hljs-type">const</span>]] [[<span class="hljs-keyword">const_cast</span>]] [[<span class="hljs-keyword">constexpr</span>]] -[[<span class="hljs-keyword">continue</span>]] [[<span class="hljs-keyword">decltype</span>]] [[<span class="hljs-keyword">default</span>]] [[<span class="hljs-keyword">delete</span>]] [[<span class="hljs-keyword">do</span>]] [[<span class="hljs-type">double</span>]] -[[<span class="hljs-keyword">dynamic_cast</span>]] [[<span class="hljs-keyword">else</span>]] [[<span class="hljs-keyword">enum</span>]] [[<span class="hljs-keyword">explicit</span>]] [[<span class="hljs-keyword">export</span>]] [[<span class="hljs-keyword">extern</span>]] [[<span class="hljs-literal">false</span>]] -[[<span class="hljs-keyword">final</span>]] [[<span class="hljs-type">float</span>]] [[<span class="hljs-keyword">for</span>]] [[<span class="hljs-keyword">friend</span>]] [[<span class="hljs-keyword">goto</span>]] [[<span class="hljs-keyword">if</span>]] [[<span class="hljs-keyword">inline</span>]] [[<span class="hljs-type">int</span>]] -[[<span class="hljs-type">long</span>]] [[<span class="hljs-keyword">mutable</span>]] [[<span class="hljs-keyword">namespace</span>]] [[<span class="hljs-keyword">new</span>]] [[<span class="hljs-keyword">noexcept</span>]] [[<span class="hljs-keyword">not</span>]] [[<span class="hljs-keyword">not_eq</span>]] -[[<span class="hljs-literal">nullptr</span>]] [[<span class="hljs-keyword">operator</span>]] [[<span class="hljs-keyword">or</span>]] [[<span class="hljs-keyword">or_eq</span>]] [[<span class="hljs-keyword">override</span>]] [[<span class="hljs-keyword">private</span>]] -[[<span class="hljs-keyword">protected</span>]] [[<span class="hljs-keyword">public</span>]] [[<span class="hljs-keyword">register</span>]] [[<span class="hljs-keyword">reinterpret_cast</span>]] [[<span class="hljs-keyword">return</span>]] [[<span class="hljs-type">short</span>]] -[[<span class="hljs-type">signed</span>]] [[<span class="hljs-keyword">sizeof</span>]] [[<span class="hljs-type">static</span>]] [[<span class="hljs-keyword">static_assert</span>]] [[<span class="hljs-keyword">static_cast</span>]] [[<span class="hljs-keyword">struct</span>]] -[[<span class="hljs-keyword">switch</span>]] [[<span class="hljs-keyword">template</span>]] [[<span class="hljs-keyword">this</span>]] [[<span class="hljs-keyword">thread_local</span>]] [[<span class="hljs-keyword">throw</span>]] [[<span class="hljs-literal">true</span>]] [[<span class="hljs-keyword">try</span>]] -[[<span class="hljs-keyword">typedef</span>]] [[<span class="hljs-keyword">typeid</span>]] [[<span class="hljs-keyword">typename</span>]] [[<span class="hljs-keyword">union</span>]] [[<span class="hljs-type">unsigned</span>]] -[[<span class="hljs-keyword">virtual</span>]] [[<span class="hljs-type">void</span>]] [[<span class="hljs-keyword">volatile</span>]] [[<span class="hljs-type">wchar_t</span>]] [[<span class="hljs-keyword">while</span>]] [[<span class="hljs-keyword">xor</span>]] [[<span class="hljs-keyword">xor_eq</span>]] -<span class="hljs-comment">// [[using]]</span> -<span class="hljs-type">int</span> <span class="hljs-built_in">main</span>() { - std::cout << <span class="hljs-string">"Hello, World!"</span> << std::endl; -}</code></pre> + <div class="codeblock" language="cpp"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">#include</span><span style="color:#032F62"> <iostream></span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">alignas</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">alignof</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">and</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">and_eq</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">asm</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">auto</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">bitand</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">bitor</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">bool</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">break</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">case</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">catch</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">char</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">char16_t</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">char32_t</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">class</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">compl</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">const</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">const_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">constexpr</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">continue</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">decltype</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">default</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">delete</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">do</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">double</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">dynamic_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">else</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">enum</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">explicit</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">export</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">extern</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">false</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">final</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">float</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">for</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">friend</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">goto</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">if</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">inline</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">int</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">long</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">mutable</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">namespace</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">new</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">noexcept</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">not</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">not_eq</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">nullptr</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">operator</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">or</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">or_eq</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">override</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">private</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">protected</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">public</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">register</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">reinterpret_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">return</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">short</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">signed</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">sizeof</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">static</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">static_assert</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">static_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">struct</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">switch</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">template</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">this</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">thread_local</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">throw</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">true</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">try</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">typedef</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">typeid</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">typename</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">union</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">unsigned</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">virtual</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">void</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">volatile</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">wchar_t</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">while</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">xor</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">xor_eq</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#6A737D">// [[using]]</span></span> +<span class="line"><span style="color:#D73A49">int</span><span style="color:#6F42C1"> main</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#6F42C1"> std</span><span style="color:#24292E">::cout </span><span style="color:#D73A49"><<</span><span style="color:#032F62"> "Hello, World!"</span><span style="color:#D73A49"> <<</span><span style="color:#6F42C1"> std</span><span style="color:#24292E">::endl;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <blockquote> <p> @@ -137,8 +138,10 @@ 上のコードでは <code>[[using]]</code> をコメントアウトしているが、これは <code>using</code> キーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。 </p> - <pre class="highlight" language="cpp"><code class="highlight"><span class="hljs-comment">// using の例</span> -[[<span class="hljs-keyword">using</span> foo: attr1, attr2]] <span class="hljs-type">int</span> x; <span class="hljs-comment">// [[foo::attr1, foo::attr2]] の糖衣構文</span></code></pre> + <div class="codeblock" language="cpp"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">// using の例</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#D73A49">using</span><span style="color:#6F42C1"> foo</span><span style="color:#005CC5">: </span><span style="color:#6F42C1">attr1</span><span style="color:#005CC5">, </span><span style="color:#6F42C1">attr2</span><span style="color:#005CC5">]]</span><span style="color:#D73A49"> int</span><span style="color:#24292E"> x;</span><span style="color:#6A737D"> // [[foo::attr1, foo::attr2]] の糖衣構文</span></span></code></pre> + </div> <p> C++17 の仕様も見てみる (正確には標準化前のドラフト)。 diff --git a/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html b/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html index 91ec5d0a..f3a11356 100644 --- a/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html +++ b/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -78,13 +77,15 @@ Python でクロージャを作ろうと、次のようなコードを書いた。 </p> - <pre class="highlight" language="python"><code class="highlight"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>(): - x = <span class="hljs-number">0</span> - <span class="hljs-keyword">def</span> <span class="hljs-title function_">g</span>(): - x += <span class="hljs-number">1</span> - g() - -f()</code></pre> + <div class="codeblock" language="python"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">def</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span></span> +<span class="line"><span style="color:#D73A49"> def</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">+=</span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> g()</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">f()</span></span></code></pre> + </div> <p> 関数 <code>g</code> から 関数 <code>f</code> のスコープ内で定義された変数 <code>x</code> を参照し、それに 1 を足そうとしている。 これを実行すると <code>x += 1</code> の箇所でエラーが発生する。 @@ -100,27 +101,31 @@ f()</code></pre> local変数 <code>x</code> が代入前に参照された、とある。これは、<code>f</code> の <code>x</code> を参照するのではなく、新しく別の変数を <code>g</code> 内に作ってしまっているため。前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。<code>var</code> を変数宣言のための構文として擬似的に利用している。 </p> - <pre class="highlight" language="python"><code class="highlight"><span class="hljs-comment"># 注: var は正しい Python の文法ではない。上記参照のこと</span> -<span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>(): - var x <span class="hljs-comment"># f の local変数 'x' を宣言</span> - x = <span class="hljs-number">0</span> <span class="hljs-comment"># x に 0 を代入</span> - <span class="hljs-keyword">def</span> <span class="hljs-title function_">g</span>(): <span class="hljs-comment"># f の内部関数 g を定義</span> - var x <span class="hljs-comment"># g の local変数 'x' を宣言</span> - <span class="hljs-comment"># たまたま f にも同じ名前の変数があるが、それとは別の変数</span> - x += <span class="hljs-number">1</span> <span class="hljs-comment"># x に 1 を加算 (x = x + 1 の糖衣構文)</span> - <span class="hljs-comment"># 加算する前の値を参照しようとするが、まだ代入されていないためエラー</span> - g()</code></pre> + <div class="codeblock" language="python"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># 注: var は正しい Python の文法ではない。上記参照のこと</span></span> +<span class="line"><span style="color:#D73A49">def</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> var x </span><span style="color:#6A737D"># f の local変数 'x' を宣言</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#6A737D"> # x に 0 を代入</span></span> +<span class="line"><span style="color:#D73A49"> def</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">(): </span><span style="color:#6A737D"># f の内部関数 g を定義</span></span> +<span class="line"><span style="color:#24292E"> var x </span><span style="color:#6A737D"># g の local変数 'x' を宣言</span></span> +<span class="line"><span style="color:#6A737D"> # たまたま f にも同じ名前の変数があるが、それとは別の変数</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">+=</span><span style="color:#005CC5"> 1</span><span style="color:#6A737D"> # x に 1 を加算 (x = x + 1 の糖衣構文)</span></span> +<span class="line"><span style="color:#6A737D"> # 加算する前の値を参照しようとするが、まだ代入されていないためエラー</span></span> +<span class="line"><span style="color:#24292E"> g()</span></span></code></pre> + </div> <p> 当初の意図を表現するには、次のように書けばよい。 </p> - <pre class="highlight" language="python"><code class="highlight"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>(): - x = <span class="hljs-number">0</span> - <span class="hljs-keyword">def</span> <span class="hljs-title function_">g</span>(): - <span class="hljs-keyword">nonlocal</span> x <span class="hljs-comment">## (*)</span> - x += <span class="hljs-number">1</span> - g()</code></pre> + <div class="codeblock" language="python"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">def</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span></span> +<span class="line"><span style="color:#D73A49"> def</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#D73A49"> nonlocal</span><span style="color:#24292E"> x </span><span style="color:#6A737D">## (*)</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">+=</span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> g()</span></span></code></pre> + </div> <p> <code>(*)</code> のように、<code>nonlocal</code> を追加する。これにより一つ外側のスコープ (<code>g</code> の一つ外側 = <code>f</code>) で定義されている <code>x</code> を探しに行くようになる。 diff --git a/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html index 0e9ee932..cf2eb729 100644 --- a/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Ruby】 自身を実行している処理系の種類を判定する|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -83,12 +82,14 @@ 上記ページの例から引用する: </p> - <pre class="highlight" language="shell-session"><code>$ ruby-1.9.1 -ve 'p RUBY_ENGINE' -ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux] -"ruby" -$ jruby -ve 'p RUBY_ENGINE' -jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] -"jruby"</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ ruby-1.9.1 -ve 'p RUBY_ENGINE'</span></span> +<span class="line"><span>ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]</span></span> +<span class="line"><span>"ruby"</span></span> +<span class="line"><span>$ jruby -ve 'p RUBY_ENGINE'</span></span> +<span class="line"><span>jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]</span></span> +<span class="line"><span>"jruby"</span></span></code></pre> + </div> <p> それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 @@ -208,10 +209,12 @@ jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] <a href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35" rel="noreferrer" target="_blank">mruby 該当部分のソース</a> より引用: </p> - <pre class="highlight" language="c"><code class="highlight"><span class="hljs-comment">/* -* Ruby engine. -*/</span> -<span class="hljs-meta">#<span class="hljs-keyword">define</span> MRUBY_RUBY_ENGINE <span class="hljs-string">"mruby"</span></span></code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/*</span></span> +<span class="line"><span style="color:#6A737D">* Ruby engine.</span></span> +<span class="line"><span style="color:#6A737D">*/</span></span> +<span class="line"><span style="color:#D73A49">#define</span><span style="color:#6F42C1"> MRUBY_RUBY_ENGINE</span><span style="color:#032F62"> "mruby"</span></span></code></pre> + </div> </div> </article> </main> diff --git a/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index a11a2f15..76f7058c 100644 --- a/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Ruby】 then キーワードと case in|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -83,36 +82,40 @@ 使われることは稀だが、Ruby では <code>then</code> がキーワードになっている。次のように使う: </p> - <pre class="highlight" language="ruby"><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> + <div class="codeblock" language="ruby"> + <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> + </div> <p> このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code> 構文がそれに当たる。 上記のように、何か条件を書いた後 <code>then</code> を置き、式がそこで終了していることを示すマーカーとして機能する。 </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-comment"># Example:</span> - -<span class="hljs-keyword">if</span> x <span class="hljs-keyword">then</span> - a -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">unless</span> x <span class="hljs-keyword">then</span> - a -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">begin</span> - a -<span class="hljs-keyword">rescue</span> <span class="hljs-keyword">then</span> - b -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">case</span> x -<span class="hljs-keyword">when</span> p <span class="hljs-keyword">then</span> - a -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <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> + </div> </section> <section id="section--why-then-is-usually-unnecessary"> @@ -121,17 +124,21 @@ 普通 Ruby のコードで <code>then</code> を書くことはない。なぜか。次のコードを実行してみるとわかる。 </p> - <pre class="highlight" language="ruby"><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> + <div class="codeblock" language="ruby"> + <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> + </div> <p> 次のような構文エラーが出力される。 </p> - <pre class="highlight"><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 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> + </div> <p> 二つ目のメッセージは無視して一つ目を読むと、<code>then</code> か <code>;</code> か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。 @@ -141,8 +148,10 @@ if true puts 'Hello, World!' end ポイントは改行が <code>then</code> (や <code>;</code>) の代わりとなることである。<code>true</code> の後に改行を入れてみる。 </p> - <pre class="highlight" language="ruby"><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> + <div class="codeblock" language="ruby"> + <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> + </div> <p> 無事 Hello, World! と出力されるようになった。 @@ -155,21 +164,27 @@ puts <span class="hljs-string">'Hello, World!'</span> <span class="hlj なぜ <code>then</code> や <code>;</code> や改行 (以下 「<code>then</code> 等」) が必要なのだろうか。次の例を見てほしい: </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">if</span> a b <span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <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> + </div> <p> <code>then</code> も <code>;</code> も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。この例は二通りに解釈できる。 </p> - <pre class="highlight" language="ruby"><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> + <div class="codeblock" language="ruby"> + <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> + </div> - <pre class="highlight" language="ruby"><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> + <div class="codeblock" language="ruby"> + <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> + </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> も同じ役割を持つ。 @@ -190,39 +205,43 @@ b <a href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986" rel="noreferrer" target="_blank">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</a> </p> - <pre class="highlight" language="yacc"><code>p_case_body : keyword_in -{ - SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); - p->command_start = FALSE; - $<ctxt>1 = p->ctxt; - p->ctxt.in_kwarg = 1; - $<tbl>$ = push_pvtbl(p); -} -{ - $<tbl>$ = push_pktbl(p); -} -p_top_expr then -{ - pop_pktbl(p, $<tbl>3); - pop_pvtbl(p, $<tbl>2); - p->ctxt.in_kwarg = $<ctxt>1.in_kwarg; -} -compstmt -p_cases -{ - /*%%%*/ - $$ = NEW_IN($4, $7, $8, &@$); - /*% %*/ - /*% ripper: in!($4, $7, escape_Qundef($8)) %*/ -} -;</code></pre> + <div class="codeblock" language="yacc"> + <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> $<ctxt>1 = p->ctxt;</span></span> +<span class="line"><span> p->ctxt.in_kwarg = 1;</span></span> +<span class="line"><span> $<tbl>$ = push_pvtbl(p);</span></span> +<span class="line"><span>}</span></span> +<span class="line"><span>{</span></span> +<span class="line"><span> $<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, $<tbl>3);</span></span> +<span class="line"><span> pop_pvtbl(p, $<tbl>2);</span></span> +<span class="line"><span> p->ctxt.in_kwarg = $<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, &@$);</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> + </div> <p> 簡略版: </p> - <pre class="highlight" language="yacc"><code>p_case_body : keyword_in p_top_expr then compstmt p_cases -;</code></pre> + <div class="codeblock" language="yacc"> + <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> + </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>、改行のいずれかである。 @@ -232,36 +251,40 @@ p_cases これにより、<code>case</code> - <code>when</code> による従来の構文と同じように、<code>then</code> 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる: </p> - <pre class="highlight" language="ruby"><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 -<span class="hljs-keyword">in</span> <span class="hljs-number">3</span> <span class="hljs-keyword">then</span> c -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">case</span> x -<span class="hljs-keyword">in</span> <span class="hljs-number">1</span> - a -<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> - -<span class="hljs-keyword">case</span> x -<span class="hljs-keyword">in</span> <span class="hljs-number">1</span>; a -<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> + <div class="codeblock" language="ruby"> + <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> + </div> <p> ところで、<code>p_top_expr</code> には <code>if</code> による guard clause が書けるので、その場合は <code>if</code> - <code>then</code> と似たような見た目になる。 </p> - <pre class="highlight" language="ruby"><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> + <div class="codeblock" language="ruby"> + <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"><</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> + </div> </section> <section id="section--outro"> diff --git a/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index 69cfb8a4..4ae7f235 100644 --- a/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>Rust のプリミティブ型はどこからやって来るか|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -73,26 +72,28 @@ Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-meta">#![allow(non_camel_case_types)]</span> -<span class="hljs-meta">#![allow(dead_code)]</span> - -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">bool</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">char</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i8</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i16</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i32</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i64</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i128</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">isize</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u8</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u16</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u32</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u64</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u128</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">usize</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">f32</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">f64</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">str</span>;</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">#![allow(non_camel_case_types)]</span></span> +<span class="line"><span style="color:#24292E">#![allow(dead_code)]</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> bool</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> char</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i8</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i16</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i32</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i64</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i128</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> isize</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u8</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u16</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u32</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u64</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u128</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> usize</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> f32</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> f64</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> str</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> では、普段単に <code>bool</code> と書いたとき、この <code>bool</code> は一体どこから来ているのか。rustc のソースを追ってみた。 @@ -127,60 +128,66 @@ <code>rustc</code> はセルフホストされている (= <code>rustc</code> 自身が Rust で書かれている) ので、<code>bool</code> や <code>char</code> などで適当に検索をかけてもノイズが多すぎて話にならない。しかし、お誂え向きなことに <code>i128</code>/<code>u128</code> というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使って <code>git grep</code> してみる。 </p> - <pre class="highlight"><code>$ git grep "\bi128\b" | wc # i128 -165 1069 15790 - -$ git grep "\bu128\b" | wc # u128 -293 2127 26667 - -$ git grep "\bbool\b" | wc # cf. bool の結果 -3563 23577 294659</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ git grep "\bi128\b" | wc # i128</span></span> +<span class="line"><span>165 1069 15790</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ git grep "\bu128\b" | wc # u128</span></span> +<span class="line"><span>293 2127 26667</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ git grep "\bbool\b" | wc # cf. bool の結果</span></span> +<span class="line"><span>3563 23577 294659</span></span></code></pre> + </div> <p> 165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。 </p> - <pre class="highlight"><code>$ git grep "\bi128\b" -... -rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); -...</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ git grep "\bi128\b"</span></span> +<span class="line"><span>...</span></span> +<span class="line"><span>rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));</span></span> +<span class="line"><span>...</span></span></code></pre> + </div> <p> <code>rustc_resolve</code> というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-comment">/// Interns the names of the primitive types.</span> -<span class="hljs-comment">///</span> -<span class="hljs-comment">/// All other types are defined somewhere and possibly imported, but the primitive ones need</span> -<span class="hljs-comment">/// special handling, since they have no place of origin.</span> -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">PrimitiveTypeTable</span> { - primitive_types: FxHashMap<Symbol, PrimTy>, -} - -<span class="hljs-keyword">impl</span> <span class="hljs-title class_">PrimitiveTypeTable</span> { - <span class="hljs-keyword">fn</span> <span class="hljs-title function_">new</span>() <span class="hljs-punctuation">-></span> PrimitiveTypeTable { - <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">table</span> = FxHashMap::<span class="hljs-title function_ invoke__">default</span>(); - - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">bool</span>, Bool); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">char</span>, Char); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">f32</span>, <span class="hljs-title function_ invoke__">Float</span>(FloatTy::F32)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">f64</span>, <span class="hljs-title function_ invoke__">Float</span>(FloatTy::F64)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">isize</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::Isize)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i8</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I8)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i16</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I16)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i32</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I32)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i64</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I64)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i128</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I128)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">str</span>, Str); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">usize</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::Usize)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u8</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U8)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u16</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U16)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u32</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U32)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u64</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U64)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u128</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U128)); - <span class="hljs-keyword">Self</span> { primitive_types: table } - } -}</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/// Interns the names of the primitive types.</span></span> +<span class="line"><span style="color:#6A737D">///</span></span> +<span class="line"><span style="color:#6A737D">/// All other types are defined somewhere and possibly imported, but the primitive ones need</span></span> +<span class="line"><span style="color:#6A737D">/// special handling, since they have no place of origin.</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> PrimitiveTypeTable</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> primitive_types</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> FxHashMap</span><span style="color:#24292E"><</span><span style="color:#6F42C1">Symbol</span><span style="color:#24292E">, </span><span style="color:#6F42C1">PrimTy</span><span style="color:#24292E">>,</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">impl</span><span style="color:#6F42C1"> PrimitiveTypeTable</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> fn</span><span style="color:#6F42C1"> new</span><span style="color:#24292E">() </span><span style="color:#D73A49">-></span><span style="color:#6F42C1"> PrimitiveTypeTable</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> let</span><span style="color:#D73A49"> mut</span><span style="color:#24292E"> table </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> FxHashMap</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">default</span><span style="color:#24292E">();</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">bool</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Bool</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">char</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Char</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">f32</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Float</span><span style="color:#24292E">(</span><span style="color:#6F42C1">FloatTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">F32</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">f64</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Float</span><span style="color:#24292E">(</span><span style="color:#6F42C1">FloatTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">F64</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">isize</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Isize</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i8</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I8</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i16</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I16</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i32</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I32</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i64</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I64</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i128</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I128</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">str</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Str</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">usize</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Usize</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u8</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U8</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u16</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U16</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u32</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U32</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u64</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U64</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u128</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U128</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#005CC5"> Self</span><span style="color:#24292E"> { primitive_types</span><span style="color:#D73A49">:</span><span style="color:#24292E"> table }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、 @@ -196,27 +203,29 @@ rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-comment">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.</span> -<span class="hljs-comment">/// (略)</span> -<span class="hljs-keyword">fn</span> <span class="hljs-title function_">resolve_ident_in_lexical_scope</span>( - &<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>, - <span class="hljs-keyword">mut</span> ident: Ident, - ns: Namespace, - <span class="hljs-comment">// (略)</span> -) <span class="hljs-punctuation">-></span> <span class="hljs-type">Option</span><LexicalScopeBinding<<span class="hljs-symbol">'a</span>>> { - <span class="hljs-comment">// (略)</span> - - <span class="hljs-keyword">if</span> ns == TypeNS { - <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-variable">Some</span>(prim_ty) = <span class="hljs-keyword">self</span>.primitive_type_table.primitive_types.<span class="hljs-title function_ invoke__">get</span>(&ident.name) { - <span class="hljs-keyword">let</span> <span class="hljs-variable">binding</span> = - (Res::<span class="hljs-title function_ invoke__">PrimTy</span>(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::<span class="hljs-title function_ invoke__">root</span>()) - .<span class="hljs-title function_ invoke__">to_name_binding</span>(<span class="hljs-keyword">self</span>.arenas); - <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Some</span>(LexicalScopeBinding::<span class="hljs-title function_ invoke__">Item</span>(binding)); - } - } - - <span class="hljs-literal">None</span> -}</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.</span></span> +<span class="line"><span style="color:#6A737D">/// (略)</span></span> +<span class="line"><span style="color:#D73A49">fn</span><span style="color:#6F42C1"> resolve_ident_in_lexical_scope</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#D73A49"> &mut</span><span style="color:#005CC5"> self</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#D73A49"> mut</span><span style="color:#24292E"> ident</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> Ident</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> ns</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> Namespace</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#6A737D"> // (略)</span></span> +<span class="line"><span style="color:#24292E">) </span><span style="color:#D73A49">-></span><span style="color:#6F42C1"> Option</span><span style="color:#24292E"><</span><span style="color:#6F42C1">LexicalScopeBinding</span><span style="color:#24292E"><'</span><span style="color:#6F42C1">a</span><span style="color:#24292E">>> {</span></span> +<span class="line"><span style="color:#6A737D"> // (略)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ns </span><span style="color:#D73A49">==</span><span style="color:#6F42C1"> TypeNS</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> let</span><span style="color:#6F42C1"> Some</span><span style="color:#24292E">(prim_ty) </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> self</span><span style="color:#D73A49">.</span><span style="color:#24292E">primitive_type_table</span><span style="color:#D73A49">.</span><span style="color:#24292E">primitive_types</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">get</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">ident</span><span style="color:#D73A49">.</span><span style="color:#24292E">name) {</span></span> +<span class="line"><span style="color:#D73A49"> let</span><span style="color:#24292E"> binding </span><span style="color:#D73A49">=</span></span> +<span class="line"><span style="color:#24292E"> (</span><span style="color:#6F42C1">Res</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">PrimTy</span><span style="color:#24292E">(</span><span style="color:#D73A49">*</span><span style="color:#24292E">prim_ty), </span><span style="color:#6F42C1">ty</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Visibility</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Public</span><span style="color:#24292E">, </span><span style="color:#005CC5">DUMMY_SP</span><span style="color:#24292E">, </span><span style="color:#6F42C1">ExpnId</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">root</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#D73A49"> .</span><span style="color:#6F42C1">to_name_binding</span><span style="color:#24292E">(</span><span style="color:#005CC5">self</span><span style="color:#D73A49">.</span><span style="color:#24292E">arenas);</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#6F42C1"> Some</span><span style="color:#24292E">(</span><span style="color:#6F42C1">LexicalScopeBinding</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Item</span><span style="color:#24292E">(binding));</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> None</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。<code>if ns == TypeNS</code> のブロック内では、<code>primitive_type_table</code> (上記の <code>PrimitiveTypeTable::new()</code> で作られた変数) に含まれている識別子 (<code>bool</code>、<code>i32</code> など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。 @@ -234,13 +243,15 @@ rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); 動作がわかったところで、例として次のコードを考える。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-meta">#![allow(non_camel_case_types)]</span> - -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">bool</span>; - -<span class="hljs-keyword">fn</span> <span class="hljs-title function_">main</span>() { - <span class="hljs-keyword">let</span> <span class="hljs-variable">_</span>: <span class="hljs-type">bool</span> = <span class="hljs-type">bool</span>; -}</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">#![allow(non_camel_case_types)]</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> bool</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">fn</span><span style="color:#6F42C1"> main</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#D73A49"> let</span><span style="color:#24292E"> _</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> bool</span><span style="color:#D73A49"> =</span><span style="color:#6F42C1"> bool</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> ここで <code>main()</code> の <code>bool</code> は <code>struct bool</code> として解決される。なぜなら、プリミティブ型の判定をする前に <code>bool</code> という名前の別の型が見つかるからだ。 diff --git a/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index 72c04ee1..ddf70cae 100644 --- a/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Vim】 autocmd events の BufWrite/BufWritePre の違い|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -124,24 +123,30 @@ <a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86" rel="noreferrer" target="_blank">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</a> </p> - <pre class="highlight" language="c"><code class="highlight">{<span class="hljs-string">"BufAdd"</span>, EVENT_BUFADD}, -{<span class="hljs-string">"BufCreate"</span>, EVENT_BUFADD},</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufAdd"</span><span style="color:#24292E">, EVENT_BUFADD},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufCreate"</span><span style="color:#24292E">, EVENT_BUFADD},</span></span></code></pre> + </div> <p> <a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97" rel="noreferrer" target="_blank">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</a> </p> - <pre class="highlight" language="c"><code class="highlight">{<span class="hljs-string">"BufRead"</span>, EVENT_BUFREADPOST}, -{<span class="hljs-string">"BufReadCmd"</span>, EVENT_BUFREADCMD}, -{<span class="hljs-string">"BufReadPost"</span>, EVENT_BUFREADPOST},</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufRead"</span><span style="color:#24292E">, EVENT_BUFREADPOST},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufReadCmd"</span><span style="color:#24292E">, EVENT_BUFREADCMD},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufReadPost"</span><span style="color:#24292E">, EVENT_BUFREADPOST},</span></span></code></pre> + </div> <p> <a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105" rel="noreferrer" target="_blank">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</a> </p> - <pre class="highlight" language="c"><code class="highlight">{<span class="hljs-string">"BufWrite"</span>, EVENT_BUFWRITEPRE}, -{<span class="hljs-string">"BufWritePost"</span>, EVENT_BUFWRITEPOST}, -{<span class="hljs-string">"BufWritePre"</span>, EVENT_BUFWRITEPRE},</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufWrite"</span><span style="color:#24292E">, EVENT_BUFWRITEPRE},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufWritePost"</span><span style="color:#24292E">, EVENT_BUFWRITEPOST},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufWritePre"</span><span style="color:#24292E">, EVENT_BUFWRITEPRE},</span></span></code></pre> + </div> </section> <section id="section--code-reading--neovim"> @@ -154,20 +159,24 @@ <a href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124" rel="noreferrer" target="_blank">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</a> </p> - <pre class="highlight" language="lua"><code class="highlight">aliases = { -BufCreate = <span class="hljs-string">'BufAdd'</span>, -BufRead = <span class="hljs-string">'BufReadPost'</span>, -BufWrite = <span class="hljs-string">'BufWritePre'</span>, -FileEncoding = <span class="hljs-string">'EncodingChanged'</span>, -},</code></pre> + <div class="codeblock" language="lua"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">aliases </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> BufCreate </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'BufAdd'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> BufRead </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'BufReadPost'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> BufWrite </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'BufWritePre'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> FileEncoding </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'EncodingChanged'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">},</span></span></code></pre> + </div> <p> ところで、上では取り上げなかった <code>FileEncoding</code> だが、これは <code>:help FileEncoding</code> にしっかりと書いてある。 </p> - <pre class="highlight"><code> *FileEncoding* -FileEncoding Obsolete. It still works and is equivalent - to |EncodingChanged|.</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span> *FileEncoding*</span></span> +<span class="line"><span>FileEncoding Obsolete. It still works and is equivalent</span></span> +<span class="line"><span> to |EncodingChanged|.</span></span></code></pre> + </div> </section> </section> diff --git a/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 00a6265b..afee803f 100644 --- a/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>Vimで選択した行の順番を入れ替える|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -69,11 +68,13 @@ <section id="section--tl-dr"> <h2><a href="#section--tl-dr">TL; DR</a></h2> - <pre class="highlight" language="vim"><code class="highlight"><span class="hljs-comment">" License: Public Domain</span> - -command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ keeppatterns <span class="hljs-symbol"><line1></span>,<span class="hljs-symbol"><line2></span>g/^/<span class="hljs-keyword">m</span><span class="hljs-symbol"><line1></span>-<span class="hljs-number">1</span></code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">" License: Public Domain</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> keeppatterns <line1>,<line2>g</span><span style="color:#032F62">/^/</span><span style="color:#24292E">m<line1>-</span><span style="color:#005CC5">1</span></span></code></pre> + </div> </section> <section id="section--version"> @@ -142,9 +143,11 @@ command! -bar -<span class="hljs-built_in">range</span>=% なお、<code>:g/^/m0</code> は全ての行を入れ替えるが、<code>:N,Mg/^/mN-1</code> とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。 </p> - <pre class="highlight" language="vim"><code class="highlight">command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ <span class="hljs-symbol"><line1></span>,<span class="hljs-symbol"><line2></span>g/^/<span class="hljs-keyword">m</span><span class="hljs-symbol"><line1></span>-<span class="hljs-number">1</span></code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> <line1>,<line2>g</span><span style="color:#032F62">/^/</span><span style="color:#24292E">m<line1>-</span><span style="color:#005CC5">1</span></span></code></pre> + </div> <p> これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。 @@ -177,13 +180,15 @@ command! -bar -<span class="hljs-built_in">range</span>=% 前述した <code>:Reverse</code> コマンドの定義を少し変えて、次のようにする: </p> - <pre class="highlight" language="vim"><code class="highlight"><span class="hljs-keyword">function!</span> <span class="hljs-title">s</span>:reverse_lines<span class="hljs-params">(from, to)</span> abort - <span class="hljs-keyword">execute</span> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d,%dg/^/m%d"</span>, <span class="hljs-variable">a:from</span>, <span class="hljs-variable">a:to</span>, <span class="hljs-variable">a:from</span> - <span class="hljs-number">1</span>) -<span class="hljs-keyword">endfunction</span> - -command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ <span class="hljs-keyword">call</span> <span class="hljs-symbol"><SID></span>reverse_lines(<span class="hljs-symbol"><line1></span>, <span class="hljs-symbol"><line2></span>)</code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">function!</span><span style="color:#6F42C1"> s:reverse_lines</span><span style="color:#24292E">(from, </span><span style="color:#005CC5">to</span><span style="color:#24292E">) </span><span style="color:#D73A49">abort</span></span> +<span class="line"><span style="color:#005CC5"> execute</span><span style="color:#6F42C1"> printf</span><span style="color:#24292E">(</span><span style="color:#032F62">"%d,%dg/^/m%d"</span><span style="color:#24292E">, a:from, a:to, a:from</span><span style="color:#D73A49"> - </span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49">endfunction</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#D73A49"> call</span><span style="color:#24292E"> <</span><span style="color:#005CC5">SID</span><span style="color:#24292E">></span><span style="color:#6F42C1">reverse_lines</span><span style="color:#24292E">(<line1>, <line2>)</span></span></code></pre> + </div> <p> 実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。 @@ -234,9 +239,11 @@ command! -bar -<span class="hljs-built_in">range</span>=% </p> </blockquote> - <pre class="highlight" language="vim"><code class="highlight">command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ keeppatterns <span class="hljs-symbol"><line1></span>,<span class="hljs-symbol"><line2></span>g/^/<span class="hljs-keyword">m</span><span class="hljs-symbol"><line1></span>-<span class="hljs-number">1</span></code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> keeppatterns <line1>,<line2>g</span><span style="color:#032F62">/^/</span><span style="color:#24292E">m<line1>-</span><span style="color:#005CC5">1</span></span></code></pre> + </div> <p> まさにこのための Exコマンド、<code>:keeppatterns</code> が存在する。<code>:keeppatterns {command}</code> のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。 |
