diff options
| author | nsfisis <nsfisis@gmail.com> | 2022-12-23 23:27:09 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2023-03-06 01:46:04 +0900 |
| commit | 88ba6cfe220216f371f8756921059fac51a21262 (patch) | |
| tree | f272db2a0a3340f103df6618f19a101e65941b37 /public/posts/2021-10-02 | |
| parent | 8f988a6e899aed678406ddfac1be4ef105439274 (diff) | |
| download | blog.nsfisis.dev-88ba6cfe220216f371f8756921059fac51a21262.tar.gz blog.nsfisis.dev-88ba6cfe220216f371f8756921059fac51a21262.tar.zst blog.nsfisis.dev-88ba6cfe220216f371f8756921059fac51a21262.zip | |
AsciiDoc to DocBook
Diffstat (limited to 'public/posts/2021-10-02')
7 files changed, 1325 insertions, 1530 deletions
diff --git a/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html b/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html index d844baa..233908b 100644 --- a/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html +++ b/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> + <meta name="copyright" content="© 2021 nsfisis"> <meta name="description" content="C++ の属性構文の属性名には、キーワードが使える。ネタ記事。"> <meta name="keywords" content="C++,C++ 17"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> - <title>【C++】属性構文の属性名にはキーワードが使える | REPL: Rest-Eat-Program Loop</title> - - <link rel="stylesheet" href="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <title>【C++】 属性構文の属性名にはキーワードが使える | REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -28,183 +24,181 @@ <main class="main"> <article class="post-single"> <header class="post-header"> - <h1 class="post-title">【C++】属性構文の属性名にはキーワードが使える</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/cpp/">C++</a> - </li> - - <li class="tag"> - <a href="/tags/cpp17/">C++ 17</a> - </li> - - </ul> - + <h1 class="post-title">【C++】 属性構文の属性名にはキーワードが使える</h1> + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/cpp">C++</a> + </li> + <li class="tag"> + <a href="/tags/cpp17">C++ 17</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> - - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 - </li> - + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> </ol> </section> - <div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/94090937bcf860cfa93b" class="bare">https://qiita.com/nsfisis/items/94090937bcf860cfa93b</a></p> -</div> -<hr> -<div class="paragraph"> -<p>タイトル落ち。まずはこのコードを見て欲しい。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="cpp"><span class="cp">#include</span> <span class="cpf"><iostream></span><span class="cp"> -</span> -<span class="p">[[</span><span class="k">alignas</span><span class="p">]]</span> <span class="p">[[</span><span class="k">alignof</span><span class="p">]]</span> <span class="p">[[</span><span class="n">and</span><span class="p">]]</span> <span class="p">[[</span><span class="n">and_eq</span><span class="p">]]</span> <span class="p">[[</span><span class="k">asm</span><span class="p">]]</span> <span class="p">[[</span><span class="k">auto</span><span class="p">]]</span> <span class="p">[[</span><span class="n">bitand</span><span class="p">]]</span> -<span class="p">[[</span><span class="n">bitor</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">bool</span><span class="p">]]</span> <span class="p">[[</span><span class="k">break</span><span class="p">]]</span> <span class="p">[[</span><span class="k">case</span><span class="p">]]</span> <span class="p">[[</span><span class="k">catch</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">char</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">char16_t</span><span class="p">]]</span> -<span class="p">[[</span><span class="kt">char32_t</span><span class="p">]]</span> <span class="p">[[</span><span class="k">class</span><span class="p">]]</span> <span class="p">[[</span><span class="n">compl</span><span class="p">]]</span> <span class="p">[[</span><span class="k">const</span><span class="p">]]</span> <span class="p">[[</span><span class="k">const_cast</span><span class="p">]]</span> <span class="p">[[</span><span class="k">constexpr</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">continue</span><span class="p">]]</span> <span class="p">[[</span><span class="k">decltype</span><span class="p">]]</span> <span class="p">[[</span><span class="k">default</span><span class="p">]]</span> <span class="p">[[</span><span class="k">delete</span><span class="p">]]</span> <span class="p">[[</span><span class="k">do</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">double</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">dynamic_cast</span><span class="p">]]</span> <span class="p">[[</span><span class="k">else</span><span class="p">]]</span> <span class="p">[[</span><span class="k">enum</span><span class="p">]]</span> <span class="p">[[</span><span class="k">explicit</span><span class="p">]]</span> <span class="p">[[</span><span class="k">export</span><span class="p">]]</span> <span class="p">[[</span><span class="k">extern</span><span class="p">]]</span> <span class="p">[[</span><span class="nb">false</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">final</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">float</span><span class="p">]]</span> <span class="p">[[</span><span class="k">for</span><span class="p">]]</span> <span class="p">[[</span><span class="k">friend</span><span class="p">]]</span> <span class="p">[[</span><span class="k">goto</span><span class="p">]]</span> <span class="p">[[</span><span class="k">if</span><span class="p">]]</span> <span class="p">[[</span><span class="kr">inline</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">int</span><span class="p">]]</span> -<span class="p">[[</span><span class="kt">long</span><span class="p">]]</span> <span class="p">[[</span><span class="k">mutable</span><span class="p">]]</span> <span class="p">[[</span><span class="k">namespace</span><span class="p">]]</span> <span class="p">[[</span><span class="k">new</span><span class="p">]]</span> <span class="p">[[</span><span class="k">noexcept</span><span class="p">]]</span> <span class="p">[[</span><span class="n">not</span><span class="p">]]</span> <span class="p">[[</span><span class="n">not_eq</span><span class="p">]]</span> -<span class="p">[[</span><span class="nb">nullptr</span><span class="p">]]</span> <span class="p">[[</span><span class="k">operator</span><span class="p">]]</span> <span class="p">[[</span><span class="n">or</span><span class="p">]]</span> <span class="p">[[</span><span class="n">or_eq</span><span class="p">]]</span> <span class="p">[[</span><span class="k">override</span><span class="p">]]</span> <span class="p">[[</span><span class="k">private</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">protected</span><span class="p">]]</span> <span class="p">[[</span><span class="k">public</span><span class="p">]]</span> <span class="p">[[</span><span class="k">register</span><span class="p">]]</span> <span class="p">[[</span><span class="k">reinterpret_cast</span><span class="p">]]</span> <span class="p">[[</span><span class="k">return</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">short</span><span class="p">]]</span> -<span class="p">[[</span><span class="kt">signed</span><span class="p">]]</span> <span class="p">[[</span><span class="k">sizeof</span><span class="p">]]</span> <span class="p">[[</span><span class="k">static</span><span class="p">]]</span> <span class="p">[[</span><span class="k">static_assert</span><span class="p">]]</span> <span class="p">[[</span><span class="k">static_cast</span><span class="p">]]</span> <span class="p">[[</span><span class="k">struct</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">switch</span><span class="p">]]</span> <span class="p">[[</span><span class="k">template</span><span class="p">]]</span> <span class="p">[[</span><span class="k">this</span><span class="p">]]</span> <span class="p">[[</span><span class="k">thread_local</span><span class="p">]]</span> <span class="p">[[</span><span class="k">throw</span><span class="p">]]</span> <span class="p">[[</span><span class="nb">true</span><span class="p">]]</span> <span class="p">[[</span><span class="k">try</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">typedef</span><span class="p">]]</span> <span class="p">[[</span><span class="k">typeid</span><span class="p">]]</span> <span class="p">[[</span><span class="k">typename</span><span class="p">]]</span> <span class="p">[[</span><span class="k">union</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">unsigned</span><span class="p">]]</span> -<span class="p">[[</span><span class="k">virtual</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">void</span><span class="p">]]</span> <span class="p">[[</span><span class="k">volatile</span><span class="p">]]</span> <span class="p">[[</span><span class="kt">wchar_t</span><span class="p">]]</span> <span class="p">[[</span><span class="k">while</span><span class="p">]]</span> <span class="p">[[</span><span class="n">xor</span><span class="p">]]</span> <span class="p">[[</span><span class="n">xor_eq</span><span class="p">]]</span> -<span class="c1">// [[using]]</span> -<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span> - <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Hello, World!"</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> -<span class="p">}</span></code></pre> -</div> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>コンパイラのバージョン $ clang++ –version Apple clang version 11.0.0 -(clang-1100.0.33.8) Target: x86_64-apple-darwin19.6.0 Thread model: -posix InstalledDir: -/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin</p> -</div> -<div class="paragraph"> -<p>コンパイルコマンド (C17指定) $ clang –std=c++17 hoge.cpp</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>この記事から得られるものはこれ以上ないので以下は蛇足になる。</p> -</div> -<div class="paragraph"> -<p>別件で cppreference.com の -<a href="https://en.cppreference.com/w/cpp/language/identifiers">identifier -のページ</a> を読んでいた時、次の文が目に止まった。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="ulist"> -<ul> -<li> -<p>the identifiers that are keywords cannot be used for other purposes;</p> -<div class="ulist"> -<ul> -<li> -<p>The only place they can be used as non-keywords is in an -attribute-token. (e.g. <a id="private"></a> is a valid attribute) (since C++11)</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>キーワードでも属性として指定する場合は非キーワードとして使えるらしい。 -実際にやってみる。</p> -</div> -<div class="paragraph"> -<p>同サイトの <a href="https://en.cppreference.com/w/cpp/keyword">keywords のページ</a> -から一覧を拝借し、上のコードが出来上がった (C++17 -においてキーワードでないものなど、一部省いている)。 大量の警告 (unknown -attribute `〇〇' ignored) -がコンパイラから出力されるが、コンパイルできる。</p> -</div> -<div class="paragraph"> -<p>上のコードでは <code><a id="using"></a></code> をコメントアウトしているが、これは <code>using</code> -キーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="cpp"><span class="c1">// using の例</span> -<span class="p">[[</span><span class="k">using</span> <span class="n">foo</span><span class="o">:</span> <span class="n">attr1</span><span class="p">,</span> <span class="n">attr2</span><span class="p">]]</span> <span class="kt">int</span> <span class="n">x</span><span class="p">;</span> <span class="c1">// [[foo::attr1, foo::attr2]] の糖衣構文</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>C++17 の仕様も見てみる (正確には標準化前のドラフト)。</p> -</div> -<div class="paragraph"> -<p>引用元: <a href="https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4" class="bare">https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4</a></p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>If a keyword or an alternative token that satisfies the syntactic -requirements of an identifier is contained in an attribute-token, it is -considered an identifier.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>「<code>identifier</code> の構文上の要件を満たすキーワードまたは代替トークンが -<code>attribute-token</code> に含まれている場合、<code>identifier</code> -とみなされる」とある。どうやら間違いないようだ。</p> -</div> -<div class="paragraph"> -<p>ところで、代替トークン (alternative token) とは <code>and</code> (<code>&</code>) や <code>bitor</code> -(<code>|</code>) などのことだが、<code>identifier</code> -の構文上の要件を満たさないような代替トークンなどあるのか? -疑問に思って調べたところ、代替トークンという語にはダイグラフも含まれるらしい -(参考: -<a href="https://timsong-cpp.github.io/cppwp/n4659/lex.digraph">同ドラフト</a>)</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code><%</code> → <code>{</code></p> -</li> -<li> -<p><code>%></code> → <code>}</code></p> -</li> -<li> -<p><code><:</code> → <code>[</code></p> -</li> -<li> -<p><code>:></code> → <code>]</code></p> -</li> -<li> -<p><code>%:</code> → <code>#</code></p> -</li> -<li> -<p><code>%:%:</code> → <code>##</code></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>「<code>identifier</code> -の構文上の要件を満たさないような代替トークン」はこれらが当てはまると思われる。</p> -</div> -<div class="paragraph"> -<p>調べた感想: 字句解析器か構文解析器が辛そう</p> -</div> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/94090937bcf860cfa93b">https://qiita.com/nsfisis/items/94090937bcf860cfa93b</a> + </p> + + <p> + <hr> + </hr> + </p> + + <p> + タイトル落ち。まずはこのコードを見て欲しい。 + </p> + + <pre language="cpp" linenumbering="unnumbered"> + <code>#include <iostream> + +[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]] +[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]] +[[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]] +[[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]] +[[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]] +[[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]] +[[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]] +[[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]] +[[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]] +[[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]] +[[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]] +[[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]] +[[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]] +// [[using]] +int main() { +std::cout << "Hello, World!" << std::endl; +}</code> + </pre> + + <blockquote> + <p> + コンパイラのバージョン $ clang++ –version Apple clang version 11.0.0 (clang-1100.0.33.8) Target: x86_64-apple-darwin19.6.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin + </p> + + <p> + コンパイルコマンド (C17指定) $ clang –std=c++17 hoge.cpp + </p> + </blockquote> + + <p> + この記事から得られるものはこれ以上ないので以下は蛇足になる。 + </p> + + <p> + 別件で cppreference.com の<a xl:href="https://en.cppreference.com/w/cpp/language/identifiers">identifier のページ</a>を読んでいた時、次の文が目に止まった。 + </p> + + <blockquote> + <ul> + <li> + <p> + the identifiers that are keywords cannot be used for other purposes; + </p> + + <ul> + <li> + <p> + The only place they can be used as non-keywords is in an attribute-token. (e.g. [[private]] is a valid attribute) (since C++11) + </p> + </li> + </ul> + </li> + </ul> + </blockquote> + + <p> + キーワードでも属性として指定する場合は非キーワードとして使えるらしい。 実際にやってみる。 + </p> + + <p> + 同サイトの<a xl:href="https://en.cppreference.com/w/cpp/keyword">keywords のページ</a>から一覧を拝借し、上のコードが出来上がった (C++17 においてキーワードでないものなど、一部省いている)。 大量の警告 (unknown attribute `〇〇' ignored) がコンパイラから出力されるが、コンパイルできる。 + </p> + + <p> + 上のコードでは<code>[[using]]</code>をコメントアウトしているが、これは<code>using</code>キーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。 + </p> + + <pre language="cpp" linenumbering="unnumbered"> + <code>// using の例 +[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]] の糖衣構文</code> + </pre> + + <p> + C++17 の仕様も見てみる (正確には標準化前のドラフト)。 + </p> + + <p> + 引用元:<a xl:href="https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4">https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4</a> + </p> + + <blockquote> + <p> + If a keyword or an alternative token that satisfies the syntactic requirements of an identifier is contained in an attribute-token, it is considered an identifier. + </p> + </blockquote> + + <p> + 「<code>identifier</code>の構文上の要件を満たすキーワードまたは代替トークンが<code>attribute-token</code>に含まれている場合、<code>identifier</code>とみなされる」とある。どうやら間違いないようだ。 + </p> + + <p> + ところで、代替トークン (alternative token) とは<code>and</code>(<code>&</code>) や<code>bitor</code>(<code>|</code>) などのことだが、<code>identifier</code>の構文上の要件を満たさないような代替トークンなどあるのか? 疑問に思って調べたところ、代替トークンという語にはダイグラフも含まれるらしい (参考:<a xl:href="https://timsong-cpp.github.io/cppwp/n4659/lex.digraph">同ドラフト</a>) + </p> + + <ul> + <li> + <p> + <code><%</code>→<code>{</code> + </p> + </li> + + <li> + <p> + <code>%></code>→<code>}</code> + </p> + </li> + + <li> + <p> + <code><:</code>→<code>[</code> + </p> + </li> + + <li> + <p> + <code>:></code>→<code>]</code> + </p> + </li> + + <li> + <p> + <code>%:</code>→<code>#</code> + </p> + </li> + + <li> + <p> + <code>%:%:</code>→<code>##</code> + </p> + </li> + </ul> + + <p> + 「<code>identifier</code>の構文上の要件を満たさないような代替トークン」はこれらが当てはまると思われる。 + </p> + + <p> + 調べた感想: 字句解析器か構文解析器が辛そう + </p> </div> - </article> </main> <footer class="footer"> diff --git a/public/posts/2021-10-02/python-unbound-local-error/index.html b/public/posts/2021-10-02/python-unbound-local-error/index.html index bc93332..ee8d6f2 100644 --- a/public/posts/2021-10-02/python-unbound-local-error/index.html +++ b/public/posts/2021-10-02/python-unbound-local-error/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> + <meta name="copyright" content="© 2021 nsfisis"> <meta name="description" content="Python における UnboundLocalError の理由と対処法。"> <meta name="keywords" content="Python,Python 3"> <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="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <title>【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment | REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -28,105 +24,96 @@ <main class="main"> <article class="post-single"> <header class="post-header"> - <h1 class="post-title">【Python】クロージャとUnboundLocalError: local variable 'x' referenced before assignment</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/python/">Python</a> - </li> - - <li class="tag"> - <a href="/tags/python3/">Python 3</a> - </li> - - </ul> - + <h1 class="post-title">【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment</h1> + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/python">Python</a> + </li> + <li class="tag"> + <a href="/tags/python3">Python 3</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> - - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 - </li> - + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> </ol> </section> - <div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/5d733703afcb35bbf399" class="bare">https://qiita.com/nsfisis/items/5d733703afcb35bbf399</a></p> -</div> -<hr> -<div class="paragraph"> -<p>本記事は Python 3.7.6 の動作結果を元にして書かれている。</p> -</div> -<div class="paragraph"> -<p>Python でクロージャを作ろうと、次のようなコードを書いた。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="python"><span class="k">def</span> <span class="nf">f</span><span class="p">():</span> - <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span> - <span class="k">def</span> <span class="nf">g</span><span class="p">():</span> - <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span> - <span class="n">g</span><span class="p">()</span> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/5d733703afcb35bbf399">https://qiita.com/nsfisis/items/5d733703afcb35bbf399</a> + </p> + + <p> + <hr> + </hr> + </p> + + <p> + 本記事は Python 3.7.6 の動作結果を元にして書かれている。 + </p> + + <p> + Python でクロージャを作ろうと、次のようなコードを書いた。 + </p> + + <pre language="python" linenumbering="unnumbered"> + <code>def f(): +x = 0 +def g(): +x += 1 +g() -<span class="n">f</span><span class="p">()</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>関数 <code>g</code> から 関数 <code>f</code> のスコープ内で定義された変数 <code>x</code> を参照し、それに -1 を足そうとしている。 これを実行すると <code>x += 1</code> -の箇所でエラーが発生する。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>UnboundLocalError: local variable `x' referenced before assignment</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>local変数 <code>x</code> が代入前に参照された、とある。これは、<code>f</code> の <code>x</code> -を参照するのではなく、新しく別の変数を <code>g</code> 内に作ってしまっているため。 -前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。<code>var</code> -を変数宣言のための構文として擬似的に利用している。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="python"><span class="c1"># 注: var は正しい Python の文法ではない。上記参照のこと -</span><span class="k">def</span> <span class="nf">f</span><span class="p">():</span> - <span class="n">var</span> <span class="n">x</span> <span class="c1"># f の local変数 'x' を宣言 -</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># x に 0 を代入 -</span> <span class="k">def</span> <span class="nf">g</span><span class="p">():</span> <span class="c1"># f の内部関数 g を定義 -</span> <span class="n">var</span> <span class="n">x</span> <span class="c1"># g の local変数 'x' を宣言 -</span> <span class="c1"># たまたま f にも同じ名前の変数があるが、それとは別の変数 -</span> <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1"># x に 1 を加算 (x = x + 1 の糖衣構文) -</span> <span class="c1"># 加算する前の値を参照しようとするが、まだ代入されていないためエラー -</span> <span class="n">g</span><span class="p">()</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>当初の意図を表現するには、次のように書けばよい。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="python"><span class="k">def</span> <span class="nf">f</span><span class="p">():</span> - <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span> - <span class="k">def</span> <span class="nf">g</span><span class="p">():</span> - <span class="k">nonlocal</span> <span class="n">x</span> <span class="c1">## (*) -</span> <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span> - <span class="n">g</span><span class="p">()</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>(*)</code> のように、<code>nonlocal</code> を追加する。これにより一つ外側のスコープ (<code>g</code> -の一つ外側 = <code>f</code>) で定義されている <code>x</code> を探しに行くようになる。</p> -</div> +f()</code> + </pre> + + <p> + 関数<code>g</code>から 関数<code>f</code>のスコープ内で定義された変数<code>x</code>を参照し、それに 1 を足そうとしている。 これを実行すると<code>x += 1</code>の箇所でエラーが発生する。 + </p> + + <blockquote> + <p> + UnboundLocalError: local variable `x' referenced before assignment + </p> + </blockquote> + + <p> + local変数<code>x</code>が代入前に参照された、とある。これは、<code>f</code>の<code>x</code>を参照するのではなく、新しく別の変数を<code>g</code>内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。<code>var</code>を変数宣言のための構文として擬似的に利用している。 + </p> + + <pre language="python" linenumbering="unnumbered"> + <code># 注: var は正しい Python の文法ではない。上記参照のこと +def f(): +var x # f の local変数 'x' を宣言 +x = 0 # x に 0 を代入 +def g(): # f の内部関数 g を定義 +var x # g の local変数 'x' を宣言 +# たまたま f にも同じ名前の変数があるが、それとは別の変数 +x += 1 # x に 1 を加算 (x = x + 1 の糖衣構文) +# 加算する前の値を参照しようとするが、まだ代入されていないためエラー +g()</code> + </pre> + + <p> + 当初の意図を表現するには、次のように書けばよい。 + </p> + + <pre language="python" linenumbering="unnumbered"> + <code>def f(): +x = 0 +def g(): +nonlocal x ## (*) +x += 1 +g()</code> + </pre> + + <p> + <code>(*)</code>のように、<code>nonlocal</code>を追加する。これにより一つ外側のスコープ (<code>g</code>の一つ外側 =<code>f</code>) で定義されている<code>x</code>を探しに行くようになる。 + </p> </div> - </article> </main> <footer class="footer"> diff --git a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html index dac7277..cf04687 100644 --- a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> - <meta name="description" content="Ruby には複数の実装があるが、自身を実行している処理系の種類を スクリプト上からどのように判定すればよいだろうか。"> + <meta name="copyright" content="© 2021 nsfisis"> + <meta name="description" content="Ruby には複数の実装があるが、自身を実行している処理系の種類をスクリプト上からどのように判定すればよいだろうか。"> <meta name="keywords" content="Ruby"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> - <title>【Ruby】自身を実行している処理系の種類を判定する | REPL: Rest-Eat-Program Loop</title> - - <link rel="stylesheet" href="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <title>【Ruby】 自身を実行している処理系の種類を判定する | REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -28,141 +24,181 @@ <main class="main"> <article class="post-single"> <header class="post-header"> - <h1 class="post-title">【Ruby】自身を実行している処理系の種類を判定する</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/ruby/">Ruby</a> - </li> - - </ul> - + <h1 class="post-title">【Ruby】 自身を実行している処理系の種類を判定する</h1> + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/ruby">Ruby</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> - - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 - </li> - + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> </ol> </section> - <div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791" class="bare">https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791</a></p> -</div> -<hr> -<div class="paragraph"> -<p>Ruby -という言語には複数の実装があるが、それらをスクリプト上からどのようにして -programmatically に見分ければよいだろうか。</p> -</div> -<div class="paragraph"> -<p><code>Object</code> クラスに定義されている <code>RUBY_ENGINE</code> -という定数がこの用途に使える。</p> -</div> -<div class="paragraph"> -<p>参考: -<a href="https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_ENGINE.html">Object::RUBY_ENGINE</a></p> -</div> -<div class="paragraph"> -<p>上記ページの例から引用する:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="shell-session"><span class="gp">$</span><span class="w"> </span>ruby-1.9.1 <span class="nt">-ve</span> <span class="s1">'p RUBY_ENGINE'</span> -<span class="go">ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux] -"ruby" -</span><span class="gp">$</span><span class="w"> </span>jruby <span class="nt">-ve</span> <span class="s1">'p RUBY_ENGINE'</span> -<span class="go">jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] -"jruby"</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>それぞれの処理系がどのような値を返すかだが、stack overflow -に良い質問と回答があった。</p> -</div> -<div class="paragraph"> -<p><a href="https://stackoverflow.com/a/9894232">What values for RUBY_ENGINE -correspond to which Ruby implementations?</a> より引用:</p> -</div> -<div class="quoteblock"> -<blockquote> -<table class="tableblock frame-all grid-all stretch"> -<colgroup> -<col style="width: 50%;"> -<col style="width: 50%;"> -</colgroup> -<thead> -<tr> -<th class="tableblock halign-center valign-top">RUBY_ENGINE</th> -<th class="tableblock halign-left valign-top">Implementation</th> -</tr> -</thead> -<tbody> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock"><undefined></p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">MRI < 1.9</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`ruby'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">MRI >= 1.9 or REE</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`jruby'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">JRuby</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`macruby'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">MacRuby</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`rbx'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Rubinius</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`maglev'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">MagLev</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`ironruby'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">IronRuby</p></td> -</tr> -<tr> -<td class="tableblock halign-center valign-top"><p class="tableblock">`cardinal'</p></td> -<td class="tableblock halign-left valign-top"><p class="tableblock">Cardinal</p></td> -</tr> -</tbody> -</table> -</blockquote> -</div> -<div class="paragraph"> -<p>なお、この質問・回答は -2014年になされたものであり、値は変わっている可能性がある。MRI (aka -CRuby) については執筆時現在 (2020/12/8) も <code>'ruby'</code> -が返ってくることを確認済み。</p> -</div> -<div class="paragraph"> -<p>この表にない主要な処理系として、https://mruby.org[mruby] は <code>'mruby'</code> -を返す。</p> -</div> -<div class="paragraph"> -<p><a href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35">mruby -該当部分のソース</a> より引用:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="c"><span class="cm">/* - * Ruby engine. - */</span> -<span class="cp">#define MRUBY_RUBY_ENGINE "mruby"</span></code></pre> -</div> -</div> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791">https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791</a> + </p> + + <p> + <hr> + </hr> + </p> + + <p> + Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。 + </p> + + <p> + <code>Object</code>クラスに定義されている<code>RUBY_ENGINE</code>という定数がこの用途に使える。 + </p> + + <p> + 参考:<a xl:href="https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_ENGINE.html">Object::RUBY_ENGINE</a> + </p> + + <p> + 上記ページの例から引用する: + </p> + + <pre language="shell-session" linenumbering="unnumbered"> + <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> + + <p> + それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 + </p> + + <p> + <a xl:href="https://stackoverflow.com/a/9894232">What values for RUBY_ENGINE correspond to which Ruby implementations?</a>より引用: + </p> + + <blockquote> + <table> + <thead> + <tr> + <td> + RUBY_ENGINE + </td> + + <td> + Implementation + </td> + </tr> + </thead> + + <tbody> + <tr> + <td> + <undefined> + </td> + + <td> + MRI < 1.9 + </td> + </tr> + + <tr> + <td> + `ruby' + </td> + + <td> + MRI >= 1.9 or REE + </td> + </tr> + + <tr> + <td> + `jruby' + </td> + + <td> + JRuby + </td> + </tr> + + <tr> + <td> + `macruby' + </td> + + <td> + MacRuby + </td> + </tr> + + <tr> + <td> + `rbx' + </td> + + <td> + Rubinius + </td> + </tr> + + <tr> + <td> + `maglev' + </td> + + <td> + MagLev + </td> + </tr> + + <tr> + <td> + `ironruby' + </td> + + <td> + IronRuby + </td> + </tr> + + <tr> + <td> + `cardinal' + </td> + + <td> + Cardinal + </td> + </tr> + </tbody> + </table> + </blockquote> + + <p> + なお、この質問・回答は 2014年になされたものであり、値は変わっている可能性がある。MRI (aka CRuby) については執筆時現在 (2020/12/8) も<code>'ruby'</code>が返ってくることを確認済み。 + </p> + + <p> + この表にない主要な処理系として、https://mruby.org[mruby] は<code>'mruby'</code>を返す。 + </p> + + <p> + <a xl:href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35">mruby 該当部分のソース</a>より引用: + </p> + + <pre language="c" linenumbering="unnumbered"> + <code>/* +* Ruby engine. +*/ +#define MRUBY_RUBY_ENGINE "mruby"</code> + </pre> </div> - </article> </main> <footer class="footer"> diff --git a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index 62f6c43..2c6e31c 100644 --- a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> + <meta name="copyright" content="© 2021 nsfisis"> <meta name="description" content="Ruby 3.0 で追加される case in 構文と、then キーワードについて。"> <meta name="keywords" content="Ruby,Ruby 3"> <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="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <title>【Ruby】 then キーワードと case in | REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -28,336 +24,283 @@ <main class="main"> <article class="post-single"> <header class="post-header"> - <h1 class="post-title">【Ruby】then キーワードと case in</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/ruby/">Ruby</a> - </li> - - <li class="tag"> - <a href="/tags/ruby3/">Ruby 3</a> - </li> - - </ul> - + <h1 class="post-title">【Ruby】 then キーワードと case in</h1> + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/ruby">Ruby</a> + </li> + <li class="tag"> + <a href="/tags/ruby3">Ruby 3</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> - - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 - </li> - + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> </ol> </section> - <div id="preamble"> -<div class="sectionbody"> -<div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/787a8cf888a304497223" class="bare">https://qiita.com/nsfisis/items/787a8cf888a304497223</a></p> -</div> -<hr> -</div> -</div> -<section class="section-1"> - <h2 id="" class="section-header"> - - TL; DR - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p><code>case</code> - <code>in</code> によるパターンマッチング構文でも、<code>case</code> - <code>when</code> -と同じように <code>then</code> が使える (場合によっては使う必要がある)。</p> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - <code>then</code> とは - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>使われることは稀だが、Ruby では <code>then</code> -がキーワードになっている。次のように使う:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="k">if</span> <span class="n">cond</span> <span class="k">then</span> - <span class="nb">puts</span> <span class="s2">"Y"</span> -<span class="k">else</span> - <span class="nb">puts</span> <span class="s2">"N"</span> -<span class="k">end</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code> -構文がそれに当たる。 上記のように、何か条件を書いた後 <code>then</code> -を置き、式がそこで終了していることを示すマーカーとして機能する。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="c1"># Example:</span> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/787a8cf888a304497223">https://qiita.com/nsfisis/items/787a8cf888a304497223</a> + </p> + + <p> + <hr> + </hr> + </p> + + <section id="section--_tl_dr"> + <h2><a href="#section--_tl_dr">TL; DR</a></h2> + <p> + <code>case</code>-<code>in</code>によるパターンマッチング構文でも、<code>case</code>-<code>when</code>と同じように<code>then</code>が使える (場合によっては使う必要がある)。 + </p> + </section> + + <section id="section--_then_とは"> + <h2><a href="#section--_then_とは"><code>then</code>とは</a></h2> + <p> + 使われることは稀だが、Ruby では<code>then</code>がキーワードになっている。次のように使う: + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code>if cond then + puts "Y" + else + puts "N" + end</code> + </pre> + + <p> + このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code>構文がそれに当たる。 上記のように、何か条件を書いた後<code>then</code>を置き、式がそこで終了していることを示すマーカーとして機能する。 + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code># Example: -<span class="k">if</span> <span class="n">x</span> <span class="k">then</span> - <span class="n">a</span> -<span class="k">end</span> +if x then +a +end -<span class="k">unless</span> <span class="n">x</span> <span class="k">then</span> - <span class="n">a</span> -<span class="k">end</span> +unless x then +a +end -<span class="k">begin</span> - <span class="n">a</span> -<span class="k">rescue</span> <span class="k">then</span> - <span class="n">b</span> -<span class="k">end</span> +begin +a +rescue then +b +end -<span class="k">case</span> <span class="n">x</span> -<span class="k">when</span> <span class="nb">p</span> <span class="k">then</span> - <span class="n">a</span> -<span class="k">end</span></code></pre> -</div> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - なぜ普段は書かなくてもよいのか - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>普通 Ruby のコードで <code>then</code> -を書くことはない。なぜか。次のコードを実行してみるとわかる。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="k">if</span> <span class="kp">true</span> <span class="nb">puts</span> <span class="s1">'Hello, World!'</span> <span class="k">end</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>次のような構文エラーが出力される。</p> -</div> -<div class="literalblock"> -<div class="content"> -<pre>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</pre> -</div> -</div> -<div class="paragraph"> -<p>二つ目のメッセージは無視して一つ目を読むと、<code>then</code> か <code>;</code> -か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。</p> -</div> -<div class="paragraph"> -<p>ポイントは改行が <code>then</code> (や <code>;</code>) の代わりとなることである。<code>true</code> -の後に改行を入れてみる。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="k">if</span> <span class="kp">true</span> -<span class="nb">puts</span> <span class="s1">'Hello, World!'</span> <span class="k">end</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>無事 Hello, World! と出力されるようになった。</p> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - なぜ <code>then</code> や <code>;</code> や改行が必要か - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>なぜ <code>then</code> や <code>;</code> や改行 (以下 「<code>then</code> 等」) -が必要なのだろうか。次の例を見てほしい:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="k">if</span> <span class="n">a</span> <span class="n">b</span> <span class="k">end</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>then</code> も <code>;</code> -も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 -この例は二通りに解釈できる。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="c1"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span> -<span class="k">if</span> <span class="n">a</span> <span class="k">then</span> - <span class="n">b</span> -<span class="k">end</span></code></pre> -</div> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="c1"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span> -<span class="c1"># その結果が truthy なら何もしない</span> -<span class="k">if</span> <span class="n">a</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="k">then</span> -<span class="k">end</span></code></pre> -</div> -</div> -<div class="paragraph"> -<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> も同じ役割を持つ。</p> -</div> -<div class="paragraph"> -<p>Ruby の場合、プログラマーが書きやすいよう改行でもって <code>then</code> -が代用できるので、ほとんどの場合 <code>then</code> は必要ない。</p> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - <code>case</code> - <code>in</code> における <code>then</code> - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>ようやく本題にたどり着いた。来る Ruby 3.0 では <code>case</code> と <code>in</code> -キーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとして -<code>then</code> 等が必要になる。 (現在の) Ruby には formal -な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc -の説明は省略)。</p> -</div> -<div class="paragraph"> -<p><a href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986" class="bare">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</a></p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="yacc">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> -</div> -<div class="paragraph"> -<p>簡略版:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="yacc">p_case_body : keyword_in p_top_expr then compstmt p_cases - ;</code></pre> -</div> -</div> -<div class="paragraph"> -<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>、改行のいずれかである。</p> -</div> -<div class="paragraph"> -<p>これにより、<code>case</code> - <code>when</code> による従来の構文と同じように、<code>then</code> -等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="k">case</span> <span class="n">x</span> -<span class="k">in</span> <span class="mi">1</span> <span class="k">then</span> <span class="n">a</span> -<span class="k">in</span> <span class="mi">2</span> <span class="k">then</span> <span class="n">b</span> -<span class="k">in</span> <span class="mi">3</span> <span class="k">then</span> <span class="n">c</span> -<span class="k">end</span> +case x +when p then +a +end</code> + </pre> + </section> + + <section id="section--_なぜ普段は書かなくてもよいのか"> + <h2><a href="#section--_なぜ普段は書かなくてもよいのか">なぜ普段は書かなくてもよいのか</a></h2> + <p> + 普通 Ruby のコードで<code>then</code>を書くことはない。なぜか。次のコードを実行してみるとわかる。 + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code>if true puts 'Hello, World!' end</code> + </pre> + + <p> + 次のような構文エラーが出力される。 + </p> + + <pre class="monospaced"> + <code>20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n' + if true puts 'Hello, World!' end + ^~~~ + 20:1: syntax error, unexpected `end', expecting end-of-input + ...f true puts 'Hello, World!' end</code> + </pre> + + <p> + 二つ目のメッセージは無視して一つ目を読むと、<code>then</code>か<code>;</code>か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。 + </p> + + <p> + ポイントは改行が<code>then</code>(や<code>;</code>) の代わりとなることである。<code>true</code>の後に改行を入れてみる。 + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code>if true +puts 'Hello, World!' end</code> + </pre> + + <p> + 無事 Hello, World! と出力されるようになった。 + </p> + </section> + + <section id="section--_なぜ_then_や_や改行が必要か"> + <h2><a href="#section--_なぜ_then_や_や改行が必要か">なぜ<code>then</code>や<code>;</code>や改行が必要か</a></h2> + <p> + なぜ<code>then</code>や<code>;</code>や改行 (以下 「<code>then</code>等」) が必要なのだろうか。次の例を見てほしい: + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code>if a b end</code> + </pre> + + <p> + <code>then</code>も<code>;</code>も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。 + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価 +if a then +b +end</code> + </pre> + + <pre language="ruby" linenumbering="unnumbered"> + <code># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、 +# その結果が truthy なら何もしない +if a(b) then +end</code> + </pre> + + <p> + <code>then</code>等はこの曖昧性を排除するためにあり、条件式は<code>if</code>から<code>then</code>等までの間にある、ということを明確にする。 C系の<code>if</code>後に来る<code>(</code>/<code>)</code>や、Python の<code>:</code>、Rust/Go/Swift などの<code>{</code>も同じ役割を持つ。 + </p> + + <p> + Ruby の場合、プログラマーが書きやすいよう改行でもって<code>then</code>が代用できるので、ほとんどの場合<code>then</code>は必要ない。 + </p> + </section> + + <section id="section--_case_in_における_then"> + <h2><a href="#section--_case_in_における_then"><code>case</code>-<code>in</code>における<code>then</code></a></h2> + <p> + ようやく本題にたどり着いた。来る Ruby 3.0 では<code>case</code>と<code>in</code>キーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとして<code>then</code>等が必要になる。 (現在の) Ruby には formal な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc の説明は省略)。 + </p> + + <p> + <a xl:href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</a> + </p> + + <pre language="yacc" linenumbering="unnumbered"> + <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> + + <p> + 簡略版: + </p> + + <pre language="yacc" linenumbering="unnumbered"> + <code>p_case_body : keyword_in p_top_expr then compstmt p_cases +;</code> + </pre> + + <p> + ここで、<code>keyword_in</code>は文字通り<code>in</code>、<code>p_top_expr</code>はいわゆるパターン、<code>then</code>は<code>then</code>キーワードのことではなく、この記事で<code>then</code>等と呼んでいるもの、つまり<code>then</code>キーワード、<code>;</code>、改行のいずれかである。 + </p> + + <p> + これにより、<code>case</code>-<code>when</code>による従来の構文と同じように、<code>then</code>等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる: + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code>case x +in 1 then a +in 2 then b +in 3 then c +end -<span class="k">case</span> <span class="n">x</span> -<span class="k">in</span> <span class="mi">1</span> - <span class="n">a</span> -<span class="k">in</span> <span class="mi">2</span> - <span class="n">b</span> -<span class="k">in</span> <span class="mi">3</span> - <span class="n">c</span> -<span class="k">end</span> +case x +in 1 +a +in 2 +b +in 3 +c +end -<span class="k">case</span> <span class="n">x</span> -<span class="k">in</span> <span class="mi">1</span><span class="p">;</span> <span class="n">a</span> -<span class="k">in</span> <span class="mi">2</span><span class="p">;</span> <span class="n">b</span> -<span class="k">in</span> <span class="mi">3</span><span class="p">;</span> <span class="n">c</span> -<span class="k">end</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>ところで、<code>p_top_expr</code> には <code>if</code> による guard clause -が書けるので、その場合は <code>if</code> - <code>then</code> と似たような見た目になる。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="ruby"><span class="k">case</span> <span class="n">x</span> -<span class="k">in</span> <span class="mi">0</span> <span class="k">then</span> <span class="n">a</span> -<span class="k">in</span> <span class="n">n</span> <span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">0</span> <span class="k">then</span> <span class="n">b</span> -<span class="k">in</span> <span class="n">n</span> <span class="k">then</span> <span class="n">c</span> -<span class="k">end</span></code></pre> -</div> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - まとめ - - </h2> - <div class="section-body"> - <div class="ulist"> -<ul> -<li> -<p><code>if</code> や <code>case</code> の条件の後ろには <code>then</code>、<code>;</code>、改行のいずれかが必要</p> -<div class="ulist"> -<ul> -<li> -<p>通常は改行しておけばよい</p> -</li> -</ul> -</div> -</li> -<li> -<p>3.0 で入る予定の <code>case</code> - <code>in</code> でも <code>then</code> 等が必要になる</p> -</li> -<li> -<p>Ruby の構文を正確に知るには (現状) <code>parse.y</code> を直接読めばよい</p> -</li> -</ul> -</div> - </div> -</section> +case x +in 1; a +in 2; b +in 3; c +end</code> + </pre> + + <p> + ところで、<code>p_top_expr</code>には<code>if</code>による guard clause が書けるので、その場合は<code>if</code>-<code>then</code>と似たような見た目になる。 + </p> + + <pre language="ruby" linenumbering="unnumbered"> + <code>case x +in 0 then a +in n if n < 0 then b +in n then c +end</code> + </pre> + </section> + + <section id="section--_まとめ"> + <h2><a href="#section--_まとめ">まとめ</a></h2> + <ul> + <li> + <p> + <code>if</code>や<code>case</code>の条件の後ろには<code>then</code>、<code>;</code>、改行のいずれかが必要 + </p> + + <ul> + <li> + <p> + 通常は改行しておけばよい + </p> + </li> + </ul> + </li> + + <li> + <p> + 3.0 で入る予定の<code>case</code>-<code>in</code>でも<code>then</code>等が必要になる + </p> + </li> + + <li> + <p> + Ruby の構文を正確に知るには (現状)<code>parse.y</code>を直接読めばよい + </p> + </li> + </ul> + </section> </div> - </article> </main> <footer class="footer"> diff --git a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index bbcda80..76443a8 100644 --- a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> - <meta name="description" content="Rust のプリミティブ型は予約語ではなく普通の識別子である。 どのようにこれが名前解決されるのかを調べた。"> + <meta name="copyright" content="© 2021 nsfisis"> + <meta name="description" content="Rust のプリミティブ型は予約語ではなく普通の識別子である。どのようにこれが名前解決されるのかを調べた。"> <meta name="keywords" content="Rust"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>Rust のプリミティブ型はどこからやって来るか | REPL: Rest-Eat-Program Loop</title> - - <link rel="stylesheet" href="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -29,275 +25,229 @@ <article class="post-single"> <header class="post-header"> <h1 class="post-title">Rust のプリミティブ型はどこからやって来るか</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/rust/">Rust</a> - </li> - - </ul> - + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/rust">Rust</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> - - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 - </li> - + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> </ol> </section> - <div id="preamble"> -<div class="sectionbody"> -<div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/9a429432258bbcd6c565" class="bare">https://qiita.com/nsfisis/items/9a429432258bbcd6c565</a></p> -</div> -<hr> -</div> -</div> -<section class="section-1"> - <h2 id="" class="section-header"> - - 前置き - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>Rust -において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="rust"><span class="nd">#![allow(non_camel_case_types)]</span> -<span class="nd">#![allow(dead_code)]</span> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/9a429432258bbcd6c565">https://qiita.com/nsfisis/items/9a429432258bbcd6c565</a> + </p> + + <p> + <hr> + </hr> + </p> + + <section id="section--_前置き"> + <h2><a href="#section--_前置き">前置き</a></h2> + <p> + Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 + </p> + + <pre language="rust" linenumbering="unnumbered"> + <code>#![allow(non_camel_case_types)] +#![allow(dead_code)] -<span class="k">struct</span> <span class="nb">bool</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">char</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">i8</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">i16</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">i32</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">i64</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">i128</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">isize</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">u8</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">u16</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">u32</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">u64</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">u128</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">usize</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">f32</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">f64</span><span class="p">;</span> -<span class="k">struct</span> <span class="nb">str</span><span class="p">;</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>では、普段単に <code>bool</code> と書いたとき、この <code>bool</code> -は一体どこから来ているのか。rustc のソースを追ってみた。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>前提知識: 一般的なコンパイラの構造、用語。<code>rustc</code> そのものの知識は不要 -(というよりも筆者自身がよく知らない)</p> -</div> -</blockquote> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - 調査 - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>調査に使用したソース (調査時点での最新 master)</p> -</div> -<div class="paragraph"> -<p><a href="https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98" class="bare">https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98</a></p> -</div> -<div class="paragraph"> -<p>どのようにして調べるか。rustc -の構造には詳しくないため、すぐに当たりをつけるのは難しい。</p> -</div> -<div class="paragraph"> -<p>大雑把な構造としては、<code>compiler</code> フォルダ以下に <code>rustc_*</code> -という名前のクレートが数十個入っている。これがどうやら <code>rustc</code> -コマンドの実装部のようだ。</p> -</div> -<div class="paragraph"> -<p><code>rustc</code> はセルフホストされている (= <code>rustc</code> 自身が Rust で書かれている) -ので、<code>bool</code> や <code>char</code> -などで適当に検索をかけてもノイズが多すぎて話にならない。 -しかし、お誂え向きなことに <code>i128</code>/<code>u128</code> -というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使って -<code>git grep</code> してみる。</p> -</div> -<div class="literalblock"> -<div class="content"> -<pre>$ git grep "\bi128\b" | wc # i128 - 165 1069 15790 +struct bool; +struct char; +struct i8; +struct i16; +struct i32; +struct i64; +struct i128; +struct isize; +struct u8; +struct u16; +struct u32; +struct u64; +struct u128; +struct usize; +struct f32; +struct f64; +struct str;</code> + </pre> + + <p> + では、普段単に<code>bool</code>と書いたとき、この<code>bool</code>は一体どこから来ているのか。rustc のソースを追ってみた。 + </p> + + <blockquote> + <p> + 前提知識: 一般的なコンパイラの構造、用語。<code>rustc</code>そのものの知識は不要 (というよりも筆者自身がよく知らない) + </p> + </blockquote> + </section> + + <section id="section--_調査"> + <h2><a href="#section--_調査">調査</a></h2> + <p> + 調査に使用したソース (調査時点での最新 master) + </p> + + <p> + <a xl:href="https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98">https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98</a> + </p> + + <p> + どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。 + </p> + + <p> + 大雑把な構造としては、<code>compiler</code>フォルダ以下に<code>rustc_*</code>という名前のクレートが数十個入っている。これがどうやら<code>rustc</code>コマンドの実装部のようだ。 + </p> + + <p> + <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="monospaced"> + <code>$ git grep "\bi128\b" | wc # i128 +165 1069 15790 -$ git grep "\bu128\b" | wc # u128 - 293 2127 26667 +$ git grep "\bu128\b" | wc # u128 +293 2127 26667 -$ git grep "\bbool\b" | wc # cf. bool の結果 - 3563 23577 294659</pre> -</div> -</div> -<div class="paragraph"> -<p>165 -程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。</p> -</div> -<div class="literalblock"> -<div class="content"> -<pre>$ git grep "\bi128\b" +$ git grep "\bbool\b" | wc # cf. bool の結果 +3563 23577 294659</code> + </pre> + + <p> + 165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。 + </p> + + <pre class="monospaced"> + <code>$ git grep "\bi128\b" ... rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); -...</pre> -</div> -</div> -<div class="paragraph"> -<p><code>rustc_resolve</code> -というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="rust"><span class="cd">/// Interns the names of the primitive types.</span> -<span class="cd">///</span> -<span class="cd">/// All other types are defined somewhere and possibly imported, but the primitive ones need</span> -<span class="cd">/// special handling, since they have no place of origin.</span> -<span class="k">struct</span> <span class="n">PrimitiveTypeTable</span> <span class="p">{</span> - <span class="n">primitive_types</span><span class="p">:</span> <span class="n">FxHashMap</span><span class="o"><</span><span class="n">Symbol</span><span class="p">,</span> <span class="n">PrimTy</span><span class="o">></span><span class="p">,</span> -<span class="p">}</span> +...</code> + </pre> + + <p> + <code>rustc_resolve</code>というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。 + </p> + + <pre language="rust" linenumbering="unnumbered"> + <code>/// Interns the names of the primitive types. +/// +/// All other types are defined somewhere and possibly imported, but the primitive ones need +/// special handling, since they have no place of origin. +struct PrimitiveTypeTable { +primitive_types: FxHashMap<Symbol, PrimTy>, +} -<span class="k">impl</span> <span class="n">PrimitiveTypeTable</span> <span class="p">{</span> - <span class="k">fn</span> <span class="nf">new</span><span class="p">()</span> <span class="k">-></span> <span class="n">PrimitiveTypeTable</span> <span class="p">{</span> - <span class="k">let</span> <span class="k">mut</span> <span class="n">table</span> <span class="o">=</span> <span class="nn">FxHashMap</span><span class="p">::</span><span class="nf">default</span><span class="p">();</span> +impl PrimitiveTypeTable { +fn new() -> PrimitiveTypeTable { +let mut table = FxHashMap::default(); - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">bool</span><span class="p">,</span> <span class="n">Bool</span><span class="p">);</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">char</span><span class="p">,</span> <span class="n">Char</span><span class="p">);</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">f32</span><span class="p">,</span> <span class="nf">Float</span><span class="p">(</span><span class="nn">FloatTy</span><span class="p">::</span><span class="n">F32</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">f64</span><span class="p">,</span> <span class="nf">Float</span><span class="p">(</span><span class="nn">FloatTy</span><span class="p">::</span><span class="n">F64</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">isize</span><span class="p">,</span> <span class="nf">Int</span><span class="p">(</span><span class="nn">IntTy</span><span class="p">::</span><span class="n">Isize</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">i8</span><span class="p">,</span> <span class="nf">Int</span><span class="p">(</span><span class="nn">IntTy</span><span class="p">::</span><span class="n">I8</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">i16</span><span class="p">,</span> <span class="nf">Int</span><span class="p">(</span><span class="nn">IntTy</span><span class="p">::</span><span class="n">I16</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">i32</span><span class="p">,</span> <span class="nf">Int</span><span class="p">(</span><span class="nn">IntTy</span><span class="p">::</span><span class="n">I32</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">i64</span><span class="p">,</span> <span class="nf">Int</span><span class="p">(</span><span class="nn">IntTy</span><span class="p">::</span><span class="n">I64</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">i128</span><span class="p">,</span> <span class="nf">Int</span><span class="p">(</span><span class="nn">IntTy</span><span class="p">::</span><span class="n">I128</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">str</span><span class="p">,</span> <span class="n">Str</span><span class="p">);</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">usize</span><span class="p">,</span> <span class="nf">Uint</span><span class="p">(</span><span class="nn">UintTy</span><span class="p">::</span><span class="n">Usize</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">u8</span><span class="p">,</span> <span class="nf">Uint</span><span class="p">(</span><span class="nn">UintTy</span><span class="p">::</span><span class="n">U8</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">u16</span><span class="p">,</span> <span class="nf">Uint</span><span class="p">(</span><span class="nn">UintTy</span><span class="p">::</span><span class="n">U16</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">u32</span><span class="p">,</span> <span class="nf">Uint</span><span class="p">(</span><span class="nn">UintTy</span><span class="p">::</span><span class="n">U32</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">u64</span><span class="p">,</span> <span class="nf">Uint</span><span class="p">(</span><span class="nn">UintTy</span><span class="p">::</span><span class="n">U64</span><span class="p">));</span> - <span class="n">table</span><span class="nf">.insert</span><span class="p">(</span><span class="nn">sym</span><span class="p">::</span><span class="nb">u128</span><span class="p">,</span> <span class="nf">Uint</span><span class="p">(</span><span class="nn">UintTy</span><span class="p">::</span><span class="n">U128</span><span class="p">));</span> - <span class="k">Self</span> <span class="p">{</span> <span class="n">primitive_types</span><span class="p">:</span> <span class="n">table</span> <span class="p">}</span> - <span class="p">}</span> -<span class="p">}</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>これは初めに列挙したプリミティブ型の一覧と一致している。doc comment -にも、</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>All other types are defined somewhere and possibly imported, but the -primitive ones need special handling, since they have no place of -origin.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>とある。次はこの struct -の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="rust"> <span class="cd">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.</span> - <span class="cd">/// (略)</span> - <span class="k">fn</span> <span class="nf">resolve_ident_in_lexical_scope</span><span class="p">(</span> - <span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">,</span> - <span class="k">mut</span> <span class="n">ident</span><span class="p">:</span> <span class="n">Ident</span><span class="p">,</span> - <span class="n">ns</span><span class="p">:</span> <span class="n">Namespace</span><span class="p">,</span> - <span class="c1">// (略)</span> - <span class="p">)</span> <span class="k">-></span> <span class="nb">Option</span><span class="o"><</span><span class="n">LexicalScopeBinding</span><span class="o"><</span><span class="nv">'a</span><span class="o">>></span> <span class="p">{</span> - <span class="c1">// (略)</span> +table.insert(sym::bool, Bool); +table.insert(sym::char, Char); +table.insert(sym::f32, Float(FloatTy::F32)); +table.insert(sym::f64, Float(FloatTy::F64)); +table.insert(sym::isize, Int(IntTy::Isize)); +table.insert(sym::i8, Int(IntTy::I8)); +table.insert(sym::i16, Int(IntTy::I16)); +table.insert(sym::i32, Int(IntTy::I32)); +table.insert(sym::i64, Int(IntTy::I64)); +table.insert(sym::i128, Int(IntTy::I128)); +table.insert(sym::str, Str); +table.insert(sym::usize, Uint(UintTy::Usize)); +table.insert(sym::u8, Uint(UintTy::U8)); +table.insert(sym::u16, Uint(UintTy::U16)); +table.insert(sym::u32, Uint(UintTy::U32)); +table.insert(sym::u64, Uint(UintTy::U64)); +table.insert(sym::u128, Uint(UintTy::U128)); +Self { primitive_types: table } +} +}</code> + </pre> + + <p> + これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、 + </p> + + <blockquote> + <p> + All other types are defined somewhere and possibly imported, but the primitive ones need special handling, since they have no place of origin. + </p> + </blockquote> + + <p> + とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。 + </p> + + <pre language="rust" linenumbering="unnumbered"> + <code> /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. +/// (略) +fn resolve_ident_in_lexical_scope( +&mut self, +mut ident: Ident, +ns: Namespace, +// (略) +) -> Option<LexicalScopeBinding<'a>> { +// (略) - <span class="k">if</span> <span class="n">ns</span> <span class="o">==</span> <span class="n">TypeNS</span> <span class="p">{</span> - <span class="k">if</span> <span class="k">let</span> <span class="nf">Some</span><span class="p">(</span><span class="n">prim_ty</span><span class="p">)</span> <span class="o">=</span> <span class="k">self</span><span class="py">.primitive_type_table.primitive_types</span><span class="nf">.get</span><span class="p">(</span><span class="o">&</span><span class="n">ident</span><span class="py">.name</span><span class="p">)</span> <span class="p">{</span> - <span class="k">let</span> <span class="n">binding</span> <span class="o">=</span> - <span class="p">(</span><span class="nn">Res</span><span class="p">::</span><span class="nf">PrimTy</span><span class="p">(</span><span class="o">*</span><span class="n">prim_ty</span><span class="p">),</span> <span class="nn">ty</span><span class="p">::</span><span class="nn">Visibility</span><span class="p">::</span><span class="n">Public</span><span class="p">,</span> <span class="n">DUMMY_SP</span><span class="p">,</span> <span class="nn">ExpnId</span><span class="p">::</span><span class="nf">root</span><span class="p">())</span> - <span class="nf">.to_name_binding</span><span class="p">(</span><span class="k">self</span><span class="py">.arenas</span><span class="p">);</span> - <span class="k">return</span> <span class="nf">Some</span><span class="p">(</span><span class="nn">LexicalScopeBinding</span><span class="p">::</span><span class="nf">Item</span><span class="p">(</span><span class="n">binding</span><span class="p">));</span> - <span class="p">}</span> - <span class="p">}</span> +if ns == TypeNS { +if let Some(prim_ty) = self.primitive_type_table.primitive_types.get(&ident.name) { +let binding = +(Res::PrimTy(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root()) +.to_name_binding(self.arenas); +return Some(LexicalScopeBinding::Item(binding)); +} +} - <span class="nb">None</span> - <span class="p">}</span></code></pre> -</div> -</div> -<div class="paragraph"> -<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> など) -かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。</p> -</div> -<div class="paragraph"> -<p>なお、<code>ns</code> は「名前空間」を示す変数である。Rust -における名前空間はC言語におけるそれとほとんど同じで、今探している名前が関数名/変数名なのか型なのかマクロなのかを区別している。この -<code>if</code> -は、プリミティブ型に解決されるのは型を探しているときだけだ、と言っている。</p> -</div> -<div class="paragraph"> -<p>重要なのは、これが <code>resolve_ident_in_lexical_scope()</code> -の最後に書かれている点である。つまり、最初に挙げたプリミティブ型の識別子は、「名前解決の最終段階で」、「他に同名の型が見つかっていなければ」プリミティブ型として解決される。</p> -</div> -<div class="paragraph"> -<p>動作がわかったところで、例として次のコードを考える。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="rust"><span class="nd">#![allow(non_camel_case_types)]</span> +None +}</code> + </pre> + + <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>など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。 + </p> + + <p> + なお、<code>ns</code>は「名前空間」を示す変数である。Rust における名前空間はC言語におけるそれとほとんど同じで、今探している名前が関数名/変数名なのか型なのかマクロなのかを区別している。この<code>if</code>は、プリミティブ型に解決されるのは型を探しているときだけだ、と言っている。 + </p> + + <p> + 重要なのは、これが<code>resolve_ident_in_lexical_scope()</code>の最後に書かれている点である。つまり、最初に挙げたプリミティブ型の識別子は、「名前解決の最終段階で」、「他に同名の型が見つかっていなければ」プリミティブ型として解決される。 + </p> + + <p> + 動作がわかったところで、例として次のコードを考える。 + </p> + + <pre language="rust" linenumbering="unnumbered"> + <code>#![allow(non_camel_case_types)] -<span class="k">struct</span> <span class="nb">bool</span><span class="p">;</span> +struct bool; -<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> - <span class="k">let</span> <span class="n">_</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">;</span> -<span class="p">}</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>ここで <code>main()</code> の <code>bool</code> は <code>struct bool</code> -として解決される。なぜなら、プリミティブ型の判定をする前に <code>bool</code> -という名前の別の型が見つかるからだ。</p> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - まとめ - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>Rust -のプリミティブ型は予約語ではない。名前解決の最終段階で特別扱いされ、他に同名の型が見つかっていなければ対応するプリミティブ型に解決される。</p> -</div> - </div> -</section> +fn main() { +let _: bool = bool; +}</code> + </pre> + + <p> + ここで<code>main()</code>の<code>bool</code>は<code>struct bool</code>として解決される。なぜなら、プリミティブ型の判定をする前に<code>bool</code>という名前の別の型が見つかるからだ。 + </p> + </section> + + <section id="section--_まとめ"> + <h2><a href="#section--_まとめ">まとめ</a></h2> + <p> + Rust のプリミティブ型は予約語ではない。名前解決の最終段階で特別扱いされ、他に同名の型が見つかっていなければ対応するプリミティブ型に解決される。 + </p> + </section> </div> - </article> </main> <footer class="footer"> diff --git a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index 9b040ee..8144f03 100644 --- a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> - <meta name="description" content="Vim の autocmd events における BufWrite/BufWritePre がどう違うのかを調べた結果、 違いはないことがわかった。"> + <meta name="copyright" content="© 2021 nsfisis"> + <meta name="description" content="Vim の autocmd events における BufWrite/BufWritePre がどう違うのかを調べた結果、違いはないことがわかった。"> <meta name="keywords" content="Vim"> <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="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <title>【Vim】 autocmd events の BufWrite/BufWritePre の違い | REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -28,248 +24,220 @@ <main class="main"> <article class="post-single"> <header class="post-header"> - <h1 class="post-title">【Vim】autocmd events の BufWrite/BufWritePre の違い</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/vim/">Vim</a> - </li> - - </ul> - + <h1 class="post-title">【Vim】 autocmd events の BufWrite/BufWritePre の違い</h1> + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/vim">Vim</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> + </ol> + </section> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/79ab4db8564032de0b25">https://qiita.com/nsfisis/items/79ab4db8564032de0b25</a> + </p> + + <p> + <hr> + </hr> + </p> + + <section id="section--_tl_dr"> + <h2><a href="#section--_tl_dr">TL; DR</a></h2> + <p> + 違いはない。ただのエイリアス。 + </p> + </section> + + <section id="section--_調査記録"> + <h2><a href="#section--_調査記録">調査記録</a></h2> + <p> + Vim の autocmd events には似通った名前のものがいくつかある。大抵は<code>:help</code>に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 + </p> + + <ul> + <li> + <p> + <code>BufRead</code>/<code>BufReadPost</code> + </p> + </li> + + <li> + <p> + <code>BufWrite</code>/<code>BufWritePre</code> + </p> + </li> + + <li> + <p> + <code>BufAdd</code>/<code>BufCreate</code> + </p> + </li> + </ul> + + <p> + このうち、<code>BufAdd</code>/<code>BufCreate</code>に関しては、<code>:help BufCreate</code>に + </p> + + <blockquote> + <p> + The BufCreate event is for historic reasons. + </p> + </blockquote> + + <p> + とあり、おそらくは<code>BufAdd</code>のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。 + </p> + + <blockquote> + <p> + ソースコードへのリンク<a xl:href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim (調査時点での master branch)</a><a xl:href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim (上に同じ)</a> + </p> + </blockquote> + + <section id="section--_vim_のソースコード"> + <h3><a href="#section--_vim_のソースコード">vim のソースコード</a></h3> + <p> + 以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。 + </p> + + <p> + <a xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</a> + </p> - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + <pre language="c" linenumbering="unnumbered"> + <code> {"BufAdd", EVENT_BUFADD}, +{"BufCreate", EVENT_BUFADD},</code> + </pre> + + <p> + <a xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</a> + </p> + + <pre language="c" linenumbering="unnumbered"> + <code> {"BufRead", EVENT_BUFREADPOST}, +{"BufReadCmd", EVENT_BUFREADCMD}, +{"BufReadPost", EVENT_BUFREADPOST},</code> + </pre> + + <p> + <a xl:href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</a> + </p> + + <pre language="c" linenumbering="unnumbered"> + <code> {"BufWrite", EVENT_BUFWRITEPRE}, +{"BufWritePost", EVENT_BUFWRITEPOST}, +{"BufWritePre", EVENT_BUFWRITEPRE},</code> + </pre> + </section> + + <section id="section--_neovim_のソースコード"> + <h3><a href="#section--_neovim_のソースコード">neovim のソースコード</a></h3> + <p> + neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua で書かれている。以下にある通り、はっきり<code>aliases</code>と書かれている。 + </p> + + <p> + <a xl:href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</a> + </p> + + <pre language="lua" linenumbering="unnumbered"> + <code> aliases = { +BufCreate = 'BufAdd', +BufRead = 'BufReadPost', +BufWrite = 'BufWritePre', +FileEncoding = 'EncodingChanged', +},</code> + </pre> + + <p> + ところで、上では取り上げなかった<code>FileEncoding</code>だが、これは<code>:help FileEncoding</code>にしっかりと書いてある。 + </p> + + <pre class="monospaced"> + <code> *FileEncoding* +FileEncoding Obsolete. It still works and is equivalent +to |EncodingChanged|.</code> + </pre> + </section> + + <section id="section--_まとめ"> + <h3><a href="#section--_まとめ">まとめ</a></h3> + <p> + 記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。 + </p> + + <ul> + <li> + <p> + <code>BufAdd</code>/<code>BufCreate</code> + </p> + + <ul> + <li> + <p> + →<code>BufCreate</code>は歴史的な理由により (<code>`for historic reasons'') 存在しているため、新しい方 (`BufAdd</code>) を使う + </p> + </li> + </ul> + </li> + + <li> + <p> + <code>BufRead</code>/<code>BufReadPost</code> + </p> + + <ul> + <li> + <p> + →<code>BufReadPre</code>との対称性のため、あるいは<code>BufWritePost</code>との対称性のため<code>BufReadPost</code>を使う + </p> + </li> + </ul> + </li> + + <li> + <p> + <code>BufWrite</code>/<code>BufWritePre</code> + </p> + + <ul> + <li> + <p> + →<code>BufWritePost</code>との対称性のため、あるいは<code>BufReadPre</code>との対称性のため<code>BufWritePre</code>を使う + </p> + </li> + </ul> </li> + + <li> + <p> + <code>FileEncoding</code>/<code>EncodingChanged</code> + </p> + + <ul> + <li> + <p> + →<code>FileEncoding</code>は<code>`Obsolete'' と明言されているので、`EncodingChanged</code>を使う + </p> + </li> + </ul> + </li> + </ul> - </ol> + <p> + ところでこの調査で知ったのだが、<code>BufRead</code>と<code>BufWrite</code>は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら<code>Pre</code>/<code>Post</code>付きのものを使った方が分かりやすいだろう。 + </p> + </section> </section> - <div id="preamble"> -<div class="sectionbody"> -<div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/79ab4db8564032de0b25" class="bare">https://qiita.com/nsfisis/items/79ab4db8564032de0b25</a></p> -</div> -<hr> -</div> -</div> -<section class="section-1"> - <h2 id="" class="section-header"> - - TL; DR - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>違いはない。ただのエイリアス。</p> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - 調査記録 - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p>Vim の autocmd events には似通った名前のものがいくつかある。大抵は -<code>:help</code> -に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>BufRead</code>/<code>BufReadPost</code></p> -</li> -<li> -<p><code>BufWrite</code>/<code>BufWritePre</code></p> -</li> -<li> -<p><code>BufAdd</code>/<code>BufCreate</code></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>このうち、<code>BufAdd</code>/<code>BufCreate</code> に関しては、<code>:help BufCreate</code> に</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>The BufCreate event is for historic reasons.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>とあり、おそらくは <code>BufAdd</code> -のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため -vim と neovim のソースコードを調査した。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>ソースコードへのリンク -<a href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim -(調査時点での master branch)</a> -<a href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim -(上に同じ)</a></p> -</div> -</blockquote> -</div> -<section class="section-2"> - <h3 id="" class="section-header"> - - vim のソースコード - - </h3> - <div class="section-body"> - <div class="paragraph"> -<p>以下は、autocmd events -の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。</p> -</div> -<div class="paragraph"> -<p><a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86" class="bare">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</a></p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="c"> <span class="p">{</span><span class="s">"BufAdd"</span><span class="p">,</span> <span class="n">EVENT_BUFADD</span><span class="p">},</span> - <span class="p">{</span><span class="s">"BufCreate"</span><span class="p">,</span> <span class="n">EVENT_BUFADD</span><span class="p">},</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p><a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97" class="bare">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</a></p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="c"> <span class="p">{</span><span class="s">"BufRead"</span><span class="p">,</span> <span class="n">EVENT_BUFREADPOST</span><span class="p">},</span> - <span class="p">{</span><span class="s">"BufReadCmd"</span><span class="p">,</span> <span class="n">EVENT_BUFREADCMD</span><span class="p">},</span> - <span class="p">{</span><span class="s">"BufReadPost"</span><span class="p">,</span> <span class="n">EVENT_BUFREADPOST</span><span class="p">},</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p><a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105" class="bare">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</a></p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="c"> <span class="p">{</span><span class="s">"BufWrite"</span><span class="p">,</span> <span class="n">EVENT_BUFWRITEPRE</span><span class="p">},</span> - <span class="p">{</span><span class="s">"BufWritePost"</span><span class="p">,</span> <span class="n">EVENT_BUFWRITEPOST</span><span class="p">},</span> - <span class="p">{</span><span class="s">"BufWritePre"</span><span class="p">,</span> <span class="n">EVENT_BUFWRITEPRE</span><span class="p">},</span></code></pre> -</div> -</div> - </div> -</section> -<section class="section-2"> - <h3 id="" class="section-header"> - - neovim のソースコード - - </h3> - <div class="section-body"> - <div class="paragraph"> -<p>neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua -で書かれている。以下にある通り、はっきり <code>aliases</code> と書かれている。</p> -</div> -<div class="paragraph"> -<p><a href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124" class="bare">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</a></p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="lua"> <span class="n">aliases</span> <span class="o">=</span> <span class="p">{</span> - <span class="n">BufCreate</span> <span class="o">=</span> <span class="s1">'BufAdd'</span><span class="p">,</span> - <span class="n">BufRead</span> <span class="o">=</span> <span class="s1">'BufReadPost'</span><span class="p">,</span> - <span class="n">BufWrite</span> <span class="o">=</span> <span class="s1">'BufWritePre'</span><span class="p">,</span> - <span class="n">FileEncoding</span> <span class="o">=</span> <span class="s1">'EncodingChanged'</span><span class="p">,</span> - <span class="p">},</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>ところで、上では取り上げなかった <code>FileEncoding</code> だが、これは -<code>:help FileEncoding</code> にしっかりと書いてある。</p> -</div> -<div class="literalblock"> -<div class="content"> -<pre> *FileEncoding* -FileEncoding Obsolete. It still works and is equivalent - to |EncodingChanged|.</pre> -</div> -</div> - </div> -</section> -<section class="section-2"> - <h3 id="" class="section-header"> - - まとめ - - </h3> - <div class="section-body"> - <div class="paragraph"> -<p>記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。</p> -</div> -<div class="ulist"> -<ul> -<li> -<p><code>BufAdd</code>/<code>BufCreate</code></p> -<div class="ulist"> -<ul> -<li> -<p>→ <code>BufCreate</code> は歴史的な理由により (<code>`for historic reasons'') -存在しているため、新しい方 (`BufAdd</code>) を使う</p> -</li> -</ul> -</div> -</li> -<li> -<p><code>BufRead</code>/<code>BufReadPost</code></p> -<div class="ulist"> -<ul> -<li> -<p>→ <code>BufReadPre</code> との対称性のため、あるいは <code>BufWritePost</code> -との対称性のため <code>BufReadPost</code> を使う</p> -</li> -</ul> -</div> -</li> -<li> -<p><code>BufWrite</code>/<code>BufWritePre</code></p> -<div class="ulist"> -<ul> -<li> -<p>→ <code>BufWritePost</code> との対称性のため、あるいは <code>BufReadPre</code> -との対称性のため <code>BufWritePre</code> を使う</p> -</li> -</ul> -</div> -</li> -<li> -<p><code>FileEncoding</code>/<code>EncodingChanged</code></p> -<div class="ulist"> -<ul> -<li> -<p>→ <code>FileEncoding</code> は <code>`Obsolete'' -と明言されているので、`EncodingChanged</code> を使う</p> -</li> -</ul> -</div> -</li> -</ul> -</div> -<div class="paragraph"> -<p>ところでこの調査で知ったのだが、<code>BufRead</code> と <code>BufWrite</code> -は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら -<code>Pre</code>/<code>Post</code> 付きのものを使った方が分かりやすいだろう。</p> -</div> - </div> -</section> - </div> -</section> </div> - </article> </main> <footer class="footer"> diff --git a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 8b94185..14beb7f 100644 --- a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -4,18 +4,14 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="nsfisis"> - <meta name="copyright" content="© nsfisis"> + <meta name="copyright" content="© 2021 nsfisis"> <meta name="description" content="Vim で選択した行の順番を入れ替える方法。"> <meta name="keywords" content="Vim"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>Vimで選択した行の順番を入れ替える | REPL: Rest-Eat-Program Loop</title> - - <link rel="stylesheet" href="/hl.css?208c52e3b7c9db1cad782c5d30b4698f"> - - <link rel="stylesheet" href="/style.css?779b1a3debcaeba619f6fe500e93d525"> - - <link rel="stylesheet" href="/custom.css?a649ea3528d4b626fb636505d94c1144"> - + <link rel="stylesheet" href="/hl.css?h=208c52e3b7c9db1cad782c5d30b4698f"> + <link rel="stylesheet" href="/style.css?h=779b1a3debcaeba619f6fe500e93d525"> + <link rel="stylesheet" href="/custom.css?h=a649ea3528d4b626fb636505d94c1144"> </head> <body class="single"> <header class="header"> @@ -29,299 +25,220 @@ <article class="post-single"> <header class="post-header"> <h1 class="post-title">Vimで選択した行の順番を入れ替える</h1> - - <ul class="post-tags"> - - <li class="tag"> - <a href="/tags/vim/">Vim</a> - </li> - - </ul> - + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/vim">Vim</a> + </li> + </ul> </header> <div class="post-content"> <section> <h2 id="changelog">更新履歴</h2> <ol> + <li class="revision"> + <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 + </li> + </ol> + </section> + <p> + この記事は Qiita から移植してきたものです。 元 URL:<a xl:href="https://qiita.com/nsfisis/items/4fefb361d9a693803520">https://qiita.com/nsfisis/items/4fefb361d9a693803520</a> + </p> + + <p> + <hr> + </hr> + </p> + + <section id="section--_バージョン情報"> + <h2><a href="#section--_バージョン情報">バージョン情報</a></h2> + <p> + <code>:version</code>の一部 + </p> + + <blockquote> + <p> + VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jan 26 2020 11:30:30) macOS version Included patches: 1-148 Huge version without GUI. + </p> + </blockquote> + </section> + + <section id="section--_よく紹介されている手法"> + <h2><a href="#section--_よく紹介されている手法">よく紹介されている手法</a></h2> + <section id="section--_tac_tail"> + <h3><a href="#section--_tac_tail"><code>tac</code>/<code>tail</code></a></h3> + <p> + <code>tac</code>や<code>tail -r</code>などの外部コマンドを<code>!</code>を使って呼び出し、置き換える。 + </p> - <li class="revision"> - <time datetime="2021-10-02">2021-10-02</time>: Qiita から移植 - </li> + <blockquote> + <p> + :h v_! + </p> + </blockquote> - </ol> + <p> + <code>tac</code>コマンドや<code>tail</code>の<code>-r</code>オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい + </p> + </section> + + <section id="section--_gm0"> + <h3><a href="#section--_gm0"><code>:g/^/m0</code></a></h3> + <p> + こちらは外部コマンドに頼らず、Vim の機能のみを使う。<code>g</code>は<code>:global</code>コマンドの、<code>m</code>は<code>:move</code>コマンドの略 + </p> + + <p> + <code>:global</code>コマンドは<code>:[range]global/{pattern}/[command]</code>のように使い、<code>[range]</code>で指定された範囲の行のうち、<code>{pattern}</code>で指定された検索パターンにマッチする行に対して、順番に<code>[command]</code>で指定された Ex コマンドを呼び出す。 + </p> + + <blockquote> + <p> + :h :global + </p> + </blockquote> + + <p> + <code>:move</code>コマンドは<code>[range]:move {address}</code>のように使い、<code>[range]</code>で指定された範囲の行を<code>{address}</code>で指定された位置に移動させる。 + </p> + + <blockquote> + <p> + :h :move + </p> + </blockquote> + + <p> + <code>:g/^/m0</code>のように組み合わせると、「すべての行を1行ずつ 0行目(1行目の上)に動かす」という動きをする。これは確かに行の入れ替えになっている。 + </p> + + <p> + なお、<code>:g/^/m0</code>は全ての行を入れ替えるが、<code>:N,Mg/^/mN-1</code>とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。 + </p> + + <pre language="vim" linenumbering="unnumbered"> + <code>command! -bar -range=% +\ Reverse +\ <line1>,<line2>g/^/m<line1>-1</code> + </pre> + + <p> + これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。 + </p> + </section> </section> - <div id="preamble"> -<div class="sectionbody"> -<div class="paragraph"> -<p>この記事は Qiita から移植してきたものです。 元 URL: -<a href="https://qiita.com/nsfisis/items/4fefb361d9a693803520" class="bare">https://qiita.com/nsfisis/items/4fefb361d9a693803520</a></p> -</div> -<hr> -</div> -</div> -<section class="section-1"> - <h2 id="" class="section-header"> - - バージョン情報 - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p><code>:version</code> の一部</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jan 26 2020 11:30:30) macOS -version Included patches: 1-148 Huge version without GUI.</p> -</div> -</blockquote> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - よく紹介されている手法 - - </h2> - <div class="section-body"> - <section class="section-2"> - <h3 id="" class="section-header"> - - <code>tac</code> / <code>tail</code> - - </h3> - <div class="section-body"> - <div class="paragraph"> -<p><code>tac</code> や <code>tail -r</code> などの外部コマンドを <code>!</code> -を使って呼び出し、置き換える。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h v_!</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p><code>tac</code> コマンドや <code>tail</code> の <code>-r</code> -オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい</p> -</div> - </div> -</section> -<section class="section-2"> - <h3 id="" class="section-header"> - - <code>:g/^/m0</code> - - </h3> - <div class="section-body"> - <div class="paragraph"> -<p>こちらは外部コマンドに頼らず、Vim の機能のみを使う。<code>g</code> は <code>:global</code> -コマンドの、<code>m</code> は <code>:move</code> コマンドの略</p> -</div> -<div class="paragraph"> -<p><code>:global</code> コマンドは <code>:[range]global/{pattern}/[command]</code> -のように使い、<code>[range]</code> で指定された範囲の行のうち、<code>{pattern}</code> -で指定された検索パターンにマッチする行に対して、順番に <code>[command]</code> -で指定された Ex コマンドを呼び出す。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h :global</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p><code>:move</code> コマンドは <code>[range]:move {address}</code> のように使い、<code>[range]</code> -で指定された範囲の行を <code>{address}</code> で指定された位置に移動させる。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h :move</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p><code>:g/^/m0</code> のように組み合わせると、「すべての行を1行ずつ -0行目(1行目の上)に動かす」という動きをする。これは確かに行の入れ替えになっている。</p> -</div> -<div class="paragraph"> -<p>なお、<code>:g/^/m0</code> は全ての行を入れ替えるが、<code>:N,Mg/^/mN-1</code> とすることで -N行目から -M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="vim">command<span class="p">!</span> <span class="p">-</span>bar <span class="p">-</span><span class="nb">range</span><span class="p">=</span>% -<span class="se"> \</span> Reverse -<span class="se"> \</span> <span class="p"><</span>line1<span class="p">>,<</span>line2<span class="p">></span><span class="k">g</span><span class="sr">/^/</span><span class="k">m</span><span class="p"><</span>line1<span class="p">></span><span class="m">-1</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。</p> -</div> - </div> -</section> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - <code>:g/^/m0</code> の問題点 - - </h2> - <div class="section-body"> - <div class="paragraph"> -<p><code>:global</code> -コマンドは各行に対してマッチングを行う際、現在の検索パターンを上書きしてしまう。<code>^</code> -は行の先頭にマッチするため、結果として全ての行がハイライトされてしまう。<code>'hlsearch'</code> -オプションを無効にしている場合その限りではないが、その場合でも直前の検索パターンが失われてしまうと -<code>n</code> コマンドなどの際に不便である。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h @/</p> -</div> -</blockquote> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - 解決策 - - </h2> - <div class="section-body"> - <div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>[2020/9/28追記] より簡潔な方法を見つけたので次節に追記した</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>前述した <code>:Reverse</code> コマンドの定義を少し変えて、次のようにする:</p> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="vim"><span class="k">function</span><span class="p">!</span> <span class="nv">s:reverse_lines</span><span class="p">(</span>from<span class="p">,</span> <span class="k">to</span><span class="p">)</span> abort - <span class="nb">execute</span> <span class="nb">printf</span><span class="p">(</span><span class="s2">"%d,%dg/^/m%d"</span><span class="p">,</span> <span class="nv">a:from</span><span class="p">,</span> <span class="nv">a:to</span><span class="p">,</span> <span class="nv">a:from</span> <span class="p">-</span> <span class="m">1</span><span class="p">)</span> -<span class="k">endfunction</span> + + <section id="section--_gm0_の問題点"> + <h2><a href="#section--_gm0_の問題点"><code>:g/^/m0</code>の問題点</a></h2> + <p> + <code>:global</code>コマンドは各行に対してマッチングを行う際、現在の検索パターンを上書きしてしまう。<code>^</code>は行の先頭にマッチするため、結果として全ての行がハイライトされてしまう。<code>'hlsearch'</code>オプションを無効にしている場合その限りではないが、その場合でも直前の検索パターンが失われてしまうと<code>n</code>コマンドなどの際に不便である。 + </p> + + <blockquote> + <p> + :h @/ + </p> + </blockquote> + </section> + + <section id="section--_解決策"> + <h2><a href="#section--_解決策">解決策</a></h2> + <blockquote> + <p> + [2020/9/28追記] より簡潔な方法を見つけたので次節に追記した + </p> + </blockquote> + + <p> + 前述した<code>:Reverse</code>コマンドの定義を少し変えて、次のようにする: + </p> + + <pre language="vim" linenumbering="unnumbered"> + <code>function! s:reverse_lines(from, to) abort + execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1) + endfunction -command<span class="p">!</span> <span class="p">-</span>bar <span class="p">-</span><span class="nb">range</span><span class="p">=</span>% -<span class="se"> \</span> Reverse -<span class="se"> \</span> <span class="k">call</span> <span class="p"><</span>SID<span class="p">></span>reverse_lines<span class="p">(<</span>line1<span class="p">>,</span> <span class="p"><</span>line2<span class="p">>)</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。</p> -</div> -<div class="paragraph"> -<p>この理由は、ユーザー定義関数を実行する際は検索パターンが一度保存され、実行が終了したあと復元されるため。結果として検索パターンが -<code>^</code> で上書きされることがなくなる。</p> -</div> -<div class="paragraph"> -<p>Vim のヘルプから該当箇所を引用する (強調は筆者による)。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h autocmd-searchpat</p> -</div> -<div class="paragraph"> -<p><strong>Autocommands do not change the current search patterns.</strong> Vim saves the -current search patterns before executing autocommands then restores them -after the autocommands finish. This means that autocommands do not -affect the strings highlighted with the `hlsearch' option.</p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>これは autocommand -の実行に関しての記述だが、これと同じことがユーザー定義関数の実行時にも適用される。このことは -<code>:nohlsearch</code> のヘルプにある。同じく該当箇所を引用する -(強調は筆者による)。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h :nohlsearch</p> -</div> -<div class="paragraph"> -<p>(略) This command doesn’t work in an autocommand, because the -highlighting state is saved and restored when executing autocommands -|autocmd-searchpat|. <strong>Same thing for when invoking a user function.</strong></p> -</div> -</blockquote> -</div> -<div class="paragraph"> -<p>この仕様により、<code>:g/^/m0</code> -の呼び出しをユーザー定義関数に切り出すことで上述の問題を解決できる。</p> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - 解決策 (改訂版) - - </h2> - <div class="section-body"> - <div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>[2020/9/28追記] より簡潔な方法を見つけたため追記する</p> -</div> -</blockquote> -</div> -<div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="vim">command<span class="p">!</span> <span class="p">-</span>bar <span class="p">-</span><span class="nb">range</span><span class="p">=</span>% -<span class="se"> \</span> Reverse -<span class="se"> \</span> <span class="k">keeppatterns</span> <span class="p"><</span>line1<span class="p">>,<</span>line2<span class="p">></span><span class="k">g</span><span class="sr">/^/</span><span class="k">m</span><span class="p"><</span>line1<span class="p">></span><span class="m">-1</span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>まさにこのための Exコマンド、<code>:keeppatterns</code> -が存在する。<code>:keeppatterns {command}</code> -のように使い、読んで字の如く、後ろに続く -Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。</p> -</div> -<div class="quoteblock"> -<blockquote> -<div class="paragraph"> -<p>:h :keeppatterns</p> -</div> -</blockquote> -</div> - </div> -</section> -<section class="section-1"> - <h2 id="" class="section-header"> - - コピペ用再掲 - - </h2> - <div class="section-body"> - <div id="source." class="listingblock"> -<div class="content"> -<pre class="rouge highlight"><code data-lang="vim"><span class="c">" License: Public Domain</span> + command! -bar -range=% + \ Reverse + \ call <SID>reverse_lines(<line1>, <line2>)</code> + </pre> + + <p> + 実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。 + </p> + + <p> + この理由は、ユーザー定義関数を実行する際は検索パターンが一度保存され、実行が終了したあと復元されるため。結果として検索パターンが<code>^</code>で上書きされることがなくなる。 + </p> + + <p> + Vim のヘルプから該当箇所を引用する (強調は筆者による)。 + </p> + + <blockquote> + <p> + :h autocmd-searchpat + </p> + + <p> + <em role="strong">Autocommands do not change the current search patterns.</em>Vim saves the current search patterns before executing autocommands then restores them after the autocommands finish. This means that autocommands do not affect the strings highlighted with the `hlsearch' option. + </p> + </blockquote> + + <p> + これは autocommand の実行に関しての記述だが、これと同じことがユーザー定義関数の実行時にも適用される。このことは<code>:nohlsearch</code>のヘルプにある。同じく該当箇所を引用する (強調は筆者による)。 + </p> + + <blockquote> + <p> + :h :nohlsearch + </p> + + <p> + (略) This command doesn’t work in an autocommand, because the highlighting state is saved and restored when executing autocommands |autocmd-searchpat|.<em role="strong">Same thing for when invoking a user function.</em> + </p> + </blockquote> + + <p> + この仕様により、<code>:g/^/m0</code>の呼び出しをユーザー定義関数に切り出すことで上述の問題を解決できる。 + </p> + </section> + + <section id="section--_解決策_改訂版"> + <h2><a href="#section--_解決策_改訂版">解決策 (改訂版)</a></h2> + <blockquote> + <p> + [2020/9/28追記] より簡潔な方法を見つけたため追記する + </p> + </blockquote> + + <pre language="vim" linenumbering="unnumbered"> + <code>command! -bar -range=% + \ Reverse + \ keeppatterns <line1>,<line2>g/^/m<line1>-1</code> + </pre> + + <p> + まさにこのための Exコマンド、<code>:keeppatterns</code>が存在する。<code>:keeppatterns {command}</code>のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。 + </p> + + <blockquote> + <p> + :h :keeppatterns + </p> + </blockquote> + </section> + + <section id="section--_コピペ用再掲"> + <h2><a href="#section--_コピペ用再掲">コピペ用再掲</a></h2> + <pre language="vim" linenumbering="unnumbered"> + <code>" License: Public Domain -command<span class="p">!</span> <span class="p">-</span>bar <span class="p">-</span><span class="nb">range</span><span class="p">=</span>% -<span class="se"> \</span> Reverse -<span class="se"> \</span> <span class="k">keeppatterns</span> <span class="p"><</span>line1<span class="p">>,<</span>line2<span class="p">></span><span class="k">g</span><span class="sr">/^/</span><span class="k">m</span><span class="p"><</span>line1<span class="p">></span><span class="m">-1</span></code></pre> -</div> -</div> - </div> -</section> + command! -bar -range=% + \ Reverse + \ keeppatterns <line1>,<line2>g/^/m<line1>-1</code> + </pre> + </section> </div> - </article> </main> <footer class="footer"> |
