diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/404.html | 2 | ||||
| -rw-r--r-- | docs/categories/index.html | 2 | ||||
| -rw-r--r-- | docs/index.html | 129 | ||||
| -rw-r--r-- | docs/index.xml | 106 | ||||
| -rw-r--r-- | docs/posts/cpp-you-can-use-keywords-in-attributes/index.html | 174 | ||||
| -rw-r--r-- | docs/posts/index.html | 129 | ||||
| -rw-r--r-- | docs/posts/index.xml | 108 | ||||
| -rw-r--r-- | docs/posts/my-first-post/index.html | 2 | ||||
| -rw-r--r-- | docs/posts/phperkaigi-2021/index.html | 2 | ||||
| -rw-r--r-- | docs/posts/python-unbound-local-error/index.html | 146 | ||||
| -rw-r--r-- | docs/posts/ruby-detect-running-implementation/index.html | 176 | ||||
| -rw-r--r-- | docs/posts/ruby-then-keyword-and-case-in/index.html | 242 | ||||
| -rw-r--r-- | docs/posts/rust-where-are-primitive-types-from/index.html | 233 | ||||
| -rw-r--r-- | docs/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html | 186 | ||||
| -rw-r--r-- | docs/posts/vim-swap-order-of-selected-lines/index.html | 199 | ||||
| -rw-r--r-- | docs/sitemap.xml | 27 |
16 files changed, 1853 insertions, 10 deletions
diff --git a/docs/404.html b/docs/404.html index 5048526..c4ccc90 100644 --- a/docs/404.html +++ b/docs/404.html @@ -16,7 +16,7 @@ <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> - <meta name="generator" content="Hugo 0.81.0" /> + <meta name="generator" content="Hugo 0.88.1" /> diff --git a/docs/categories/index.html b/docs/categories/index.html index 44d96d5..26fe617 100644 --- a/docs/categories/index.html +++ b/docs/categories/index.html @@ -16,7 +16,7 @@ <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> - <meta name="generator" content="Hugo 0.81.0" /> + <meta name="generator" content="Hugo 0.88.1" /> <link rel="alternate" type="application/rss+xml" href="https://nsfisis.github.io/categories/index.xml" title="REPL: Rest-Eat-Program Loop" /> diff --git a/docs/index.html b/docs/index.html index ec9c8f8..8e18578 100644 --- a/docs/index.html +++ b/docs/index.html @@ -16,7 +16,7 @@ <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> - <meta name="generator" content="Hugo 0.81.0" /> + <meta name="generator" content="Hugo 0.88.1" /> <link rel="alternate" type="application/rss+xml" href="https://nsfisis.github.io/index.xml" title="REPL: Rest-Eat-Program Loop" /> @@ -81,6 +81,133 @@ <article class="first-entry"> <header class="entry-header"> + <h2>Rust のプリミティブ型はどこからやって来るか</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565 + 前置き Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 +#![allow(non_camel_case_types)] #![allow(dead_code)] 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; では、普段単に bool と書いたとき、この bool は一体どこから来ているのか。rustc のソースを追ってみた。 + 前提知識: 一般的なコンパイラの構造、用語。rustc そのものの知識は不要 (というよりも筆者自身がよく知らない) + 調査 調査に使用したソース (調査時点での最新 master) +https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98 +どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。 +大雑把な構造としては、compiler フォルダ以下に rustc_* という名前のクレートが数十個入っている。これがどうやら rustc コマンドの実装部のようだ。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Ruby] then キーワードと case in</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223 + TL; DR case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。 +then とは 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う: +if cond then puts "Y" else puts "N" end このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。 +# Example: if x then a end unless x then a end begin a rescue then b end case x when p then a end なぜ普段は書かなくてもよいのか 普通 Ruby のコードで then を書くことはない。なぜか。次のコードを実行してみるとわかる。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[C++] 属性構文の属性名にはキーワードが使える [[void]] [[for]]</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b + タイトル落ち。まずはこのコードを見て欲しい。 +#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!...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Ruby] 自身を実行している処理系の種類を判定する</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791 + Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。 +Object クラスに定義されている RUBY_ENGINE という定数がこの用途に使える。 +参考: Object::RUBY_ENGINE +上記ページの例から引用する: +$ 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" それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 +What values for RUBY_ENGINE correspond to which Ruby implementations? より引用: + RUBY_ENGINE Implementation <undefined> MRI < 1....</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/ruby-detect-running-implementation/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>Vimで選択した行の順番を入れ替える</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520 + バージョン情報 :version の一部 + 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. + よく紹介されている手法 tac / tail tac や tail -r などの外部コマンドを ! を使って呼び出し、置き換える。 + :h v_! + tac コマンドや tail の -r オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい +:g/^/m0 こちらは外部コマンドに頼らず、Vim の機能のみを使う。g は :global コマンドの、m は :move コマンドの略 +:global コマンドは :[range]global/{pattern}/[command] のように使い、[range] で指定された範囲の行のうち、{pattern} で指定された検索パターンにマッチする行に対して、順番に [command] で指定された Ex コマンドを呼び出す。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Vim] autocmd events の BufWrite/BufWritePre の違い</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25 + TL; DR 違いはない。ただのエイリアス。 +調査記録 Vim の autocmd events には似通った名前のものがいくつかある。大抵は :help に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 + BufRead/BufReadPost BufWrite/BufWritePre BufAdd/BufCreate このうち、BufAdd/BufCreate に関しては、:help BufCreate に + The BufCreate event is for historic reasons. + とあり、おそらくは BufAdd のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。 + ソースコードへのリンク vim (調査時点での master branch) neovim (上に同じ) + vim のソースコード 以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。 +https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86 +{"BufAdd", EVENT_BUFADD}, {"BufCreate", EVENT_BUFADD}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97 +{"BufRead", EVENT_BUFREADPOST}, {"BufReadCmd", EVENT_BUFREADCMD}, {"BufReadPost", EVENT_BUFREADPOST}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Python] クロージャとUnboundLocalError: local variable 'x' referenced before assignment</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399 + 本記事は Python 3.7.6 の動作結果を元にして書かれている。 +Python でクロージャを作ろうと、次のようなコードを書いた。 +def f(): x = 0 def g(): x += 1 g() f() 関数 g から 関数 f のスコープ内で定義された変数 x を参照し、それに 1 を足そうとしている。 これを実行すると x += 1 の箇所でエラーが発生する。 + UnboundLocalError: local variable ‘x’ referenced before assignment + local変数 x が代入前に参照された、とある。これは、f の x を参照するのではなく、新しく別の変数を g 内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。var を変数宣言のための構文として擬似的に利用している。 +# 注: 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() 当初の意図を表現するには、次のように書けばよい。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/python-unbound-local-error/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> <h2>PHPerKaigi 2021</h2> </header> <section class="entry-content"> diff --git a/docs/index.xml b/docs/index.xml index 69009a2..2b7a17c 100644 --- a/docs/index.xml +++ b/docs/index.xml @@ -8,6 +8,112 @@ <language>ja-JP</language> <lastBuildDate>Wed, 31 Mar 2021 01:36:49 +0900</lastBuildDate><atom:link href="https://nsfisis.github.io/index.xml" rel="self" type="application/rss+xml" /> <item> + <title>Rust のプリミティブ型はどこからやって来るか</title> + <link>https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/</link> + <pubDate>Sat, 02 Oct 2021 09:39:27 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565 + 前置き Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 +#![allow(non_camel_case_types)] #![allow(dead_code)] 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; では、普段単に bool と書いたとき、この bool は一体どこから来ているのか。rustc のソースを追ってみた。 + 前提知識: 一般的なコンパイラの構造、用語。rustc そのものの知識は不要 (というよりも筆者自身がよく知らない) + 調査 調査に使用したソース (調査時点での最新 master) +https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98 +どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。 +大雑把な構造としては、compiler フォルダ以下に rustc_* という名前のクレートが数十個入っている。これがどうやら rustc コマンドの実装部のようだ。</description> + </item> + + <item> + <title>[Ruby] then キーワードと case in</title> + <link>https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/</link> + <pubDate>Sat, 02 Oct 2021 09:38:50 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223 + TL; DR case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。 +then とは 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う: +if cond then puts &#34;Y&#34; else puts &#34;N&#34; end このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。 +# Example: if x then a end unless x then a end begin a rescue then b end case x when p then a end なぜ普段は書かなくてもよいのか 普通 Ruby のコードで then を書くことはない。なぜか。次のコードを実行してみるとわかる。</description> + </item> + + <item> + <title>[C++] 属性構文の属性名にはキーワードが使える [[void]] [[for]]</title> + <link>https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/</link> + <pubDate>Sat, 02 Oct 2021 09:38:30 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b + タイトル落ち。まずはこのコードを見て欲しい。 +#include &lt;iostream&gt; [[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 &lt;&lt; &#34;Hello, World!</description> + </item> + + <item> + <title>[Ruby] 自身を実行している処理系の種類を判定する</title> + <link>https://nsfisis.github.io/posts/ruby-detect-running-implementation/</link> + <pubDate>Sat, 02 Oct 2021 09:37:50 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/ruby-detect-running-implementation/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791 + Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。 +Object クラスに定義されている RUBY_ENGINE という定数がこの用途に使える。 +参考: Object::RUBY_ENGINE +上記ページの例から引用する: +$ ruby-1.9.1 -ve 'p RUBY_ENGINE' ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux] &quot;ruby&quot; $ jruby -ve 'p RUBY_ENGINE' jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] &quot;jruby&quot; それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 +What values for RUBY_ENGINE correspond to which Ruby implementations? より引用: + RUBY_ENGINE Implementation &lt;undefined&gt; MRI &lt; 1.</description> + </item> + + <item> + <title>Vimで選択した行の順番を入れ替える</title> + <link>https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/</link> + <pubDate>Sat, 02 Oct 2021 09:37:25 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520 + バージョン情報 :version の一部 + 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. + よく紹介されている手法 tac / tail tac や tail -r などの外部コマンドを ! を使って呼び出し、置き換える。 + :h v_! + tac コマンドや tail の -r オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい +:g/^/m0 こちらは外部コマンドに頼らず、Vim の機能のみを使う。g は :global コマンドの、m は :move コマンドの略 +:global コマンドは :[range]global/{pattern}/[command] のように使い、[range] で指定された範囲の行のうち、{pattern} で指定された検索パターンにマッチする行に対して、順番に [command] で指定された Ex コマンドを呼び出す。</description> + </item> + + <item> + <title>[Vim] autocmd events の BufWrite/BufWritePre の違い</title> + <link>https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</link> + <pubDate>Sat, 02 Oct 2021 09:37:12 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25 + TL; DR 違いはない。ただのエイリアス。 +調査記録 Vim の autocmd events には似通った名前のものがいくつかある。大抵は :help に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 + BufRead/BufReadPost BufWrite/BufWritePre BufAdd/BufCreate このうち、BufAdd/BufCreate に関しては、:help BufCreate に + The BufCreate event is for historic reasons. + とあり、おそらくは BufAdd のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。 + ソースコードへのリンク vim (調査時点での master branch) neovim (上に同じ) + vim のソースコード 以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。 +https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86 +{&#34;BufAdd&#34;, EVENT_BUFADD}, {&#34;BufCreate&#34;, EVENT_BUFADD}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97 +{&#34;BufRead&#34;, EVENT_BUFREADPOST}, {&#34;BufReadCmd&#34;, EVENT_BUFREADCMD}, {&#34;BufReadPost&#34;, EVENT_BUFREADPOST}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</description> + </item> + + <item> + <title>[Python] クロージャとUnboundLocalError: local variable 'x' referenced before assignment</title> + <link>https://nsfisis.github.io/posts/python-unbound-local-error/</link> + <pubDate>Sat, 02 Oct 2021 09:32:37 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/python-unbound-local-error/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399 + 本記事は Python 3.7.6 の動作結果を元にして書かれている。 +Python でクロージャを作ろうと、次のようなコードを書いた。 +def f(): x = 0 def g(): x += 1 g() f() 関数 g から 関数 f のスコープ内で定義された変数 x を参照し、それに 1 を足そうとしている。 これを実行すると x += 1 の箇所でエラーが発生する。 + UnboundLocalError: local variable &lsquo;x&rsquo; referenced before assignment + local変数 x が代入前に参照された、とある。これは、f の x を参照するのではなく、新しく別の変数を g 内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。var を変数宣言のための構文として擬似的に利用している。 +# 注: var は正しい Python の文法ではない。上記参照のこと def f(): var x # f の local変数 &#39;x&#39; を宣言 x = 0 # x に 0 を代入 def g(): # f の内部関数 g を定義 var x # g の local変数 &#39;x&#39; を宣言 # たまたま f にも同じ名前の変数があるが、それとは別の変数 x += 1 # x に 1 を加算 (x = x + 1 の糖衣構文) # 加算する前の値を参照しようとするが、まだ代入されていないためエラー g() 当初の意図を表現するには、次のように書けばよい。</description> + </item> + + <item> <title>PHPerKaigi 2021</title> <link>https://nsfisis.github.io/posts/phperkaigi-2021/</link> <pubDate>Tue, 30 Mar 2021 23:22:40 +0900</pubDate> diff --git a/docs/posts/cpp-you-can-use-keywords-in-attributes/index.html b/docs/posts/cpp-you-can-use-keywords-in-attributes/index.html new file mode 100644 index 0000000..e53832b --- /dev/null +++ b/docs/posts/cpp-you-can-use-keywords-in-attributes/index.html @@ -0,0 +1,174 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>[C++] 属性構文の属性名にはキーワードが使える [[void]] [[for]] - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b + タイトル落ち。まずはこのコードを見て欲しい。 +#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!"> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">[C++] 属性構文の属性名にはキーワードが使える [[void]] [[for]]</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/94090937bcf860cfa93b">https://qiita.com/nsfisis/items/94090937bcf860cfa93b</a></p> +<hr> +<p>タイトル落ち。まずはこのコードを見て欲しい。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#75715e">#include</span> <span style="color:#75715e"><iostream></span><span style="color:#75715e"> +</span><span style="color:#75715e"></span> +<span style="color:#a6e22e">[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]</span> +<span style="color:#a6e22e">[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]</span> +<span style="color:#a6e22e">[[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]]</span> +<span style="color:#a6e22e">[[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]]</span> +<span style="color:#a6e22e">[[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]]</span> +<span style="color:#a6e22e">[[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]]</span> +<span style="color:#a6e22e">[[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]]</span> +<span style="color:#a6e22e">[[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]]</span> +<span style="color:#a6e22e">[[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]]</span> +<span style="color:#a6e22e">[[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]]</span> +<span style="color:#a6e22e">[[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]]</span> +<span style="color:#a6e22e">[[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]]</span> +<span style="color:#a6e22e">[[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]]</span> +<span style="color:#75715e">// [[using]] +</span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> main() { + std<span style="color:#f92672">::</span>cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Hello, World!"</span> <span style="color:#f92672"><<</span> std<span style="color:#f92672">::</span>endl; +} +</code></pre></div><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>コンパイルコマンド (C++17指定) +$ clang++ –std=c++17 hoge.cpp</p> +</blockquote> +<p>この記事から得られるものはこれ以上ないので以下は蛇足になる。</p> +<p>別件で cppreference.com の <a href="https://en.cppreference.com/w/cpp/language/identifiers">identifier のページ</a> を読んでいた時、次の文が目に止まった。</p> +<blockquote> +<ul> +<li>the identifiers that are keywords cannot be used for other purposes; +<ul> +<li>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)</li> +</ul> +</li> +</ul> +</blockquote> +<p>キーワードでも属性として指定する場合は非キーワードとして使えるらしい。 +実際にやってみる。</p> +<p>同サイトの [keywords のページ] (<a href="https://en.cppreference.com/w/cpp/keyword">https://en.cppreference.com/w/cpp/keyword</a>) から一覧を拝借し、上のコードが出来上がった (C++17 においてキーワードでないものなど、一部省いている)。 +大量の警告 (unknown attribute ‘〇〇’ ignored) がコンパイラから出力されるが、コンパイルできる。</p> +<p>上のコードでは <code>[[using]]</code> をコメントアウトしているが、これは <code>using</code> キーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#75715e">// using の例 +</span><span style="color:#75715e"></span><span style="color:#a6e22e">[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]]</span> <span style="color:#960050;background-color:#1e0010">の糖衣構文</span> +</code></pre></div><p>C++17 の仕様も見てみる (正確には標準化前のドラフト)。</p> +<p>引用元: <a 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 href="https://timsong-cpp.github.io/cppwp/n4659/lex.digraph">同ドラフト</a>)</p> +<ul> +<li><code><%</code> → <code>{</code></li> +<li><code>%></code> → <code>}</code></li> +<li><code><:</code> → <code>[</code></li> +<li><code>:></code> → <code>]</code></li> +<li><code>%:</code> → <code>#</code></li> +<li><code>%:%:</code> → <code>##</code></li> +</ul> +<p>「<code>identifier</code> の構文上の要件を満たさないような代替トークン」はこれらが当てはまると思われる。</p> +<p>調べた感想: 字句解析器か構文解析器が辛そう</p> +</div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/posts/index.html b/docs/posts/index.html index 0e22e47..f93dcb2 100644 --- a/docs/posts/index.html +++ b/docs/posts/index.html @@ -16,7 +16,7 @@ <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> - <meta name="generator" content="Hugo 0.81.0" /> + <meta name="generator" content="Hugo 0.88.1" /> <link rel="alternate" type="application/rss+xml" href="https://nsfisis.github.io/posts/index.xml" title="REPL: Rest-Eat-Program Loop" /> @@ -83,6 +83,133 @@ <article class="post-entry"> <header class="entry-header"> + <h2>Rust のプリミティブ型はどこからやって来るか</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565 + 前置き Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 +#![allow(non_camel_case_types)] #![allow(dead_code)] 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; では、普段単に bool と書いたとき、この bool は一体どこから来ているのか。rustc のソースを追ってみた。 + 前提知識: 一般的なコンパイラの構造、用語。rustc そのものの知識は不要 (というよりも筆者自身がよく知らない) + 調査 調査に使用したソース (調査時点での最新 master) +https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98 +どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。 +大雑把な構造としては、compiler フォルダ以下に rustc_* という名前のクレートが数十個入っている。これがどうやら rustc コマンドの実装部のようだ。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Ruby] then キーワードと case in</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223 + TL; DR case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。 +then とは 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う: +if cond then puts "Y" else puts "N" end このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。 +# Example: if x then a end unless x then a end begin a rescue then b end case x when p then a end なぜ普段は書かなくてもよいのか 普通 Ruby のコードで then を書くことはない。なぜか。次のコードを実行してみるとわかる。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[C++] 属性構文の属性名にはキーワードが使える [[void]] [[for]]</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b + タイトル落ち。まずはこのコードを見て欲しい。 +#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!...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Ruby] 自身を実行している処理系の種類を判定する</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791 + Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。 +Object クラスに定義されている RUBY_ENGINE という定数がこの用途に使える。 +参考: Object::RUBY_ENGINE +上記ページの例から引用する: +$ 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" それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 +What values for RUBY_ENGINE correspond to which Ruby implementations? より引用: + RUBY_ENGINE Implementation <undefined> MRI < 1....</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/ruby-detect-running-implementation/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>Vimで選択した行の順番を入れ替える</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520 + バージョン情報 :version の一部 + 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. + よく紹介されている手法 tac / tail tac や tail -r などの外部コマンドを ! を使って呼び出し、置き換える。 + :h v_! + tac コマンドや tail の -r オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい +:g/^/m0 こちらは外部コマンドに頼らず、Vim の機能のみを使う。g は :global コマンドの、m は :move コマンドの略 +:global コマンドは :[range]global/{pattern}/[command] のように使い、[range] で指定された範囲の行のうち、{pattern} で指定された検索パターンにマッチする行に対して、順番に [command] で指定された Ex コマンドを呼び出す。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Vim] autocmd events の BufWrite/BufWritePre の違い</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25 + TL; DR 違いはない。ただのエイリアス。 +調査記録 Vim の autocmd events には似通った名前のものがいくつかある。大抵は :help に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 + BufRead/BufReadPost BufWrite/BufWritePre BufAdd/BufCreate このうち、BufAdd/BufCreate に関しては、:help BufCreate に + The BufCreate event is for historic reasons. + とあり、おそらくは BufAdd のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。 + ソースコードへのリンク vim (調査時点での master branch) neovim (上に同じ) + vim のソースコード 以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。 +https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86 +{"BufAdd", EVENT_BUFADD}, {"BufCreate", EVENT_BUFADD}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97 +{"BufRead", EVENT_BUFREADPOST}, {"BufReadCmd", EVENT_BUFREADCMD}, {"BufReadPost", EVENT_BUFREADPOST}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> + <h2>[Python] クロージャとUnboundLocalError: local variable 'x' referenced before assignment</h2> + </header> + <section class="entry-content"> + <p>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399 + 本記事は Python 3.7.6 の動作結果を元にして書かれている。 +Python でクロージャを作ろうと、次のようなコードを書いた。 +def f(): x = 0 def g(): x += 1 g() f() 関数 g から 関数 f のスコープ内で定義された変数 x を参照し、それに 1 を足そうとしている。 これを実行すると x += 1 の箇所でエラーが発生する。 + UnboundLocalError: local variable ‘x’ referenced before assignment + local変数 x が代入前に参照された、とある。これは、f の x を参照するのではなく、新しく別の変数を g 内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。var を変数宣言のための構文として擬似的に利用している。 +# 注: 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() 当初の意図を表現するには、次のように書けばよい。...</p> + </section> + <footer class="entry-footer"> + <time>October 2, 2021</time> + </footer> + <a class="entry-link" href="https://nsfisis.github.io/posts/python-unbound-local-error/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> <h2>PHPerKaigi 2021</h2> </header> <section class="entry-content"> diff --git a/docs/posts/index.xml b/docs/posts/index.xml index 7c8bc9d..c836e68 100644 --- a/docs/posts/index.xml +++ b/docs/posts/index.xml @@ -6,7 +6,113 @@ <description>Recent content in Posts on REPL: Rest-Eat-Program Loop</description> <generator>Hugo -- gohugo.io</generator> <language>ja-JP</language> - <lastBuildDate>Tue, 30 Mar 2021 23:22:40 +0900</lastBuildDate><atom:link href="https://nsfisis.github.io/posts/index.xml" rel="self" type="application/rss+xml" /> + <lastBuildDate>Sat, 02 Oct 2021 09:39:27 +0900</lastBuildDate><atom:link href="https://nsfisis.github.io/posts/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title>Rust のプリミティブ型はどこからやって来るか</title> + <link>https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/</link> + <pubDate>Sat, 02 Oct 2021 09:39:27 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565 + 前置き Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 +#![allow(non_camel_case_types)] #![allow(dead_code)] 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; では、普段単に bool と書いたとき、この bool は一体どこから来ているのか。rustc のソースを追ってみた。 + 前提知識: 一般的なコンパイラの構造、用語。rustc そのものの知識は不要 (というよりも筆者自身がよく知らない) + 調査 調査に使用したソース (調査時点での最新 master) +https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98 +どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。 +大雑把な構造としては、compiler フォルダ以下に rustc_* という名前のクレートが数十個入っている。これがどうやら rustc コマンドの実装部のようだ。</description> + </item> + + <item> + <title>[Ruby] then キーワードと case in</title> + <link>https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/</link> + <pubDate>Sat, 02 Oct 2021 09:38:50 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223 + TL; DR case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。 +then とは 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う: +if cond then puts &#34;Y&#34; else puts &#34;N&#34; end このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。 +# Example: if x then a end unless x then a end begin a rescue then b end case x when p then a end なぜ普段は書かなくてもよいのか 普通 Ruby のコードで then を書くことはない。なぜか。次のコードを実行してみるとわかる。</description> + </item> + + <item> + <title>[C++] 属性構文の属性名にはキーワードが使える [[void]] [[for]]</title> + <link>https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/</link> + <pubDate>Sat, 02 Oct 2021 09:38:30 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/94090937bcf860cfa93b + タイトル落ち。まずはこのコードを見て欲しい。 +#include &lt;iostream&gt; [[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 &lt;&lt; &#34;Hello, World!</description> + </item> + + <item> + <title>[Ruby] 自身を実行している処理系の種類を判定する</title> + <link>https://nsfisis.github.io/posts/ruby-detect-running-implementation/</link> + <pubDate>Sat, 02 Oct 2021 09:37:50 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/ruby-detect-running-implementation/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791 + Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。 +Object クラスに定義されている RUBY_ENGINE という定数がこの用途に使える。 +参考: Object::RUBY_ENGINE +上記ページの例から引用する: +$ ruby-1.9.1 -ve 'p RUBY_ENGINE' ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux] &quot;ruby&quot; $ jruby -ve 'p RUBY_ENGINE' jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] &quot;jruby&quot; それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 +What values for RUBY_ENGINE correspond to which Ruby implementations? より引用: + RUBY_ENGINE Implementation &lt;undefined&gt; MRI &lt; 1.</description> + </item> + + <item> + <title>Vimで選択した行の順番を入れ替える</title> + <link>https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/</link> + <pubDate>Sat, 02 Oct 2021 09:37:25 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520 + バージョン情報 :version の一部 + 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. + よく紹介されている手法 tac / tail tac や tail -r などの外部コマンドを ! を使って呼び出し、置き換える。 + :h v_! + tac コマンドや tail の -r オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい +:g/^/m0 こちらは外部コマンドに頼らず、Vim の機能のみを使う。g は :global コマンドの、m は :move コマンドの略 +:global コマンドは :[range]global/{pattern}/[command] のように使い、[range] で指定された範囲の行のうち、{pattern} で指定された検索パターンにマッチする行に対して、順番に [command] で指定された Ex コマンドを呼び出す。</description> + </item> + + <item> + <title>[Vim] autocmd events の BufWrite/BufWritePre の違い</title> + <link>https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</link> + <pubDate>Sat, 02 Oct 2021 09:37:12 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25 + TL; DR 違いはない。ただのエイリアス。 +調査記録 Vim の autocmd events には似通った名前のものがいくつかある。大抵は :help に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 + BufRead/BufReadPost BufWrite/BufWritePre BufAdd/BufCreate このうち、BufAdd/BufCreate に関しては、:help BufCreate に + The BufCreate event is for historic reasons. + とあり、おそらくは BufAdd のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。 + ソースコードへのリンク vim (調査時点での master branch) neovim (上に同じ) + vim のソースコード 以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。 +https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86 +{&#34;BufAdd&#34;, EVENT_BUFADD}, {&#34;BufCreate&#34;, EVENT_BUFADD}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97 +{&#34;BufRead&#34;, EVENT_BUFREADPOST}, {&#34;BufReadCmd&#34;, EVENT_BUFREADCMD}, {&#34;BufReadPost&#34;, EVENT_BUFREADPOST}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</description> + </item> + + <item> + <title>[Python] クロージャとUnboundLocalError: local variable 'x' referenced before assignment</title> + <link>https://nsfisis.github.io/posts/python-unbound-local-error/</link> + <pubDate>Sat, 02 Oct 2021 09:32:37 +0900</pubDate> + + <guid>https://nsfisis.github.io/posts/python-unbound-local-error/</guid> + <description>この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399 + 本記事は Python 3.7.6 の動作結果を元にして書かれている。 +Python でクロージャを作ろうと、次のようなコードを書いた。 +def f(): x = 0 def g(): x += 1 g() f() 関数 g から 関数 f のスコープ内で定義された変数 x を参照し、それに 1 を足そうとしている。 これを実行すると x += 1 の箇所でエラーが発生する。 + UnboundLocalError: local variable &lsquo;x&rsquo; referenced before assignment + local変数 x が代入前に参照された、とある。これは、f の x を参照するのではなく、新しく別の変数を g 内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。var を変数宣言のための構文として擬似的に利用している。 +# 注: var は正しい Python の文法ではない。上記参照のこと def f(): var x # f の local変数 &#39;x&#39; を宣言 x = 0 # x に 0 を代入 def g(): # f の内部関数 g を定義 var x # g の local変数 &#39;x&#39; を宣言 # たまたま f にも同じ名前の変数があるが、それとは別の変数 x += 1 # x に 1 を加算 (x = x + 1 の糖衣構文) # 加算する前の値を参照しようとするが、まだ代入されていないためエラー g() 当初の意図を表現するには、次のように書けばよい。</description> + </item> + <item> <title>PHPerKaigi 2021</title> <link>https://nsfisis.github.io/posts/phperkaigi-2021/</link> diff --git a/docs/posts/my-first-post/index.html b/docs/posts/my-first-post/index.html index 938f48e..14671d3 100644 --- a/docs/posts/my-first-post/index.html +++ b/docs/posts/my-first-post/index.html @@ -16,7 +16,7 @@ <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> - <meta name="generator" content="Hugo 0.81.0" /> + <meta name="generator" content="Hugo 0.88.1" /> diff --git a/docs/posts/phperkaigi-2021/index.html b/docs/posts/phperkaigi-2021/index.html index 7fe33f0..1f2806c 100644 --- a/docs/posts/phperkaigi-2021/index.html +++ b/docs/posts/phperkaigi-2021/index.html @@ -28,7 +28,7 @@ AWS Lambda のカスタムランタイムで PHP を動かす <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> - <meta name="generator" content="Hugo 0.81.0" /> + <meta name="generator" content="Hugo 0.88.1" /> diff --git a/docs/posts/python-unbound-local-error/index.html b/docs/posts/python-unbound-local-error/index.html new file mode 100644 index 0000000..e3a142c --- /dev/null +++ b/docs/posts/python-unbound-local-error/index.html @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>[Python] クロージャとUnboundLocalError: local variable 'x' referenced before assignment - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/5d733703afcb35bbf399 + 本記事は Python 3.7.6 の動作結果を元にして書かれている。 +Python でクロージャを作ろうと、次のようなコードを書いた。 +def f(): x = 0 def g(): x += 1 g() f() 関数 g から 関数 f のスコープ内で定義された変数 x を参照し、それに 1 を足そうとしている。 これを実行すると x += 1 の箇所でエラーが発生する。 + UnboundLocalError: local variable ‘x’ referenced before assignment + local変数 x が代入前に参照された、とある。これは、f の x を参照するのではなく、新しく別の変数を g 内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。var を変数宣言のための構文として擬似的に利用している。 +# 注: 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() 当初の意図を表現するには、次のように書けばよい。"> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">[Python] クロージャとUnboundLocalError: local variable 'x' referenced before assignment</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/5d733703afcb35bbf399">https://qiita.com/nsfisis/items/5d733703afcb35bbf399</a></p> +<hr> +<p>本記事は Python 3.7.6 の動作結果を元にして書かれている。</p> +<p>Python でクロージャを作ろうと、次のようなコードを書いた。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>(): + x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span> + <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">g</span>(): + x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span> + g() + +f() +</code></pre></div><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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e"># 注: var は正しい Python の文法ではない。上記参照のこと</span> +<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>(): + var x <span style="color:#75715e"># f の local変数 'x' を宣言</span> + x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span> <span style="color:#75715e"># x に 0 を代入</span> + <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">g</span>(): <span style="color:#75715e"># f の内部関数 g を定義</span> + var x <span style="color:#75715e"># g の local変数 'x' を宣言</span> + <span style="color:#75715e"># たまたま f にも同じ名前の変数があるが、それとは別の変数</span> + x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span> <span style="color:#75715e"># x に 1 を加算 (x = x + 1 の糖衣構文)</span> + <span style="color:#75715e"># 加算する前の値を参照しようとするが、まだ代入されていないためエラー</span> + g() +</code></pre></div><p>当初の意図を表現するには、次のように書けばよい。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>(): + x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span> + <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">g</span>(): + <span style="color:#66d9ef">nonlocal</span> x <span style="color:#75715e">## (*)</span> + x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span> + g() +</code></pre></div><p><code>(*)</code> のように、<code>nonlocal</code> を追加する。これにより一つ外側のスコープ (<code>g</code> の一つ外側 = <code>f</code>) で定義されている <code>x</code> を探しに行くようになる。</p> +</div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/posts/ruby-detect-running-implementation/index.html b/docs/posts/ruby-detect-running-implementation/index.html new file mode 100644 index 0000000..8367a96 --- /dev/null +++ b/docs/posts/ruby-detect-running-implementation/index.html @@ -0,0 +1,176 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>[Ruby] 自身を実行している処理系の種類を判定する - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791 + Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。 +Object クラスに定義されている RUBY_ENGINE という定数がこの用途に使える。 +参考: Object::RUBY_ENGINE +上記ページの例から引用する: +$ 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" それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 +What values for RUBY_ENGINE correspond to which Ruby implementations? より引用: + RUBY_ENGINE Implementation <undefined> MRI < 1."> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">[Ruby] 自身を実行している処理系の種類を判定する</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791">https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791</a></p> +<hr> +<p>Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。</p> +<p><code>Object</code> クラスに定義されている <code>RUBY_ENGINE</code> という定数がこの用途に使える。</p> +<p>参考: <a href="https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_ENGINE.html">Object::RUBY_ENGINE</a></p> +<p>上記ページの例から引用する:</p> +<pre tabindex="0"><code class="language-shell-session" data-lang="shell-session">$ 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 href="https://stackoverflow.com/a/9894232">What values for RUBY_ENGINE correspond to which Ruby implementations?</a> より引用:</p> +<blockquote> +<table> +<thead> +<tr> +<th style="text-align:center">RUBY_ENGINE</th> +<th style="text-align:left">Implementation</th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align:center"><undefined></td> +<td style="text-align:left">MRI < 1.9</td> +</tr> +<tr> +<td style="text-align:center">‘ruby’</td> +<td style="text-align:left">MRI >= 1.9 or REE</td> +</tr> +<tr> +<td style="text-align:center">‘jruby’</td> +<td style="text-align:left">JRuby</td> +</tr> +<tr> +<td style="text-align:center">‘macruby’</td> +<td style="text-align:left">MacRuby</td> +</tr> +<tr> +<td style="text-align:center">‘rbx’</td> +<td style="text-align:left">Rubinius</td> +</tr> +<tr> +<td style="text-align:center">‘maglev’</td> +<td style="text-align:left">MagLev</td> +</tr> +<tr> +<td style="text-align:center">‘ironruby’</td> +<td style="text-align:left">IronRuby</td> +</tr> +<tr> +<td style="text-align:center">‘cardinal’</td> +<td style="text-align:left">Cardinal</td> +</tr> +</tbody> +</table> +</blockquote> +<p>なお、この質問・回答は 2014年になされたものであり、値は変わっている可能性がある。MRI (aka CRuby) については執筆時現在 (2020/12/8) も <code>'ruby'</code> が返ってくることを確認済み。</p> +<p>この表にない主要な処理系として、<a href="https://mruby.org">mruby</a> は <code>'mruby'</code> を返す。</p> +<p><a href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35">mruby 該当部分のソース</a> より引用:</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#75715e">/* +</span><span style="color:#75715e"> * Ruby engine. +</span><span style="color:#75715e"> */</span> +<span style="color:#75715e">#define MRUBY_RUBY_ENGINE "mruby" +</span></code></pre></div></div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/posts/ruby-then-keyword-and-case-in/index.html b/docs/posts/ruby-then-keyword-and-case-in/index.html new file mode 100644 index 0000000..75639bf --- /dev/null +++ b/docs/posts/ruby-then-keyword-and-case-in/index.html @@ -0,0 +1,242 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>[Ruby] then キーワードと case in - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/787a8cf888a304497223 + TL; DR case - in によるパターンマッチング構文でも、case - when と同じように then が使える (場合によっては使う必要がある)。 +then とは 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う: +if cond then puts "Y" else puts "N" end このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case 構文がそれに当たる。 上記のように、何か条件を書いた後 then を置き、式がそこで終了していることを示すマーカーとして機能する。 +# Example: if x then a end unless x then a end begin a rescue then b end case x when p then a end なぜ普段は書かなくてもよいのか 普通 Ruby のコードで then を書くことはない。なぜか。次のコードを実行してみるとわかる。"> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">[Ruby] then キーワードと case in</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/787a8cf888a304497223">https://qiita.com/nsfisis/items/787a8cf888a304497223</a></p> +<hr> +<h1 id="tl-dr">TL; DR</h1> +<p><code>case</code> - <code>in</code> によるパターンマッチング構文でも、<code>case</code> - <code>when</code> と同じように <code>then</code> が使える (場合によっては使う必要がある)。</p> +<h1 id="then-とは"><code>then</code> とは</h1> +<p>使われることは稀だが、Ruby では <code>then</code> がキーワードになっている。次のように使う:</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> cond <span style="color:#66d9ef">then</span> + puts <span style="color:#e6db74">"Y"</span> +<span style="color:#66d9ef">else</span> + puts <span style="color:#e6db74">"N"</span> +<span style="color:#66d9ef">end</span> +</code></pre></div><p>このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code> 構文がそれに当たる。 +上記のように、何か条件を書いた後 <code>then</code> を置き、式がそこで終了していることを示すマーカーとして機能する。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#75715e"># Example:</span> + +<span style="color:#66d9ef">if</span> x <span style="color:#66d9ef">then</span> + a +<span style="color:#66d9ef">end</span> + +<span style="color:#66d9ef">unless</span> x <span style="color:#66d9ef">then</span> + a +<span style="color:#66d9ef">end</span> + +<span style="color:#66d9ef">begin</span> + a +<span style="color:#66d9ef">rescue</span> <span style="color:#66d9ef">then</span> + b +<span style="color:#66d9ef">end</span> + +<span style="color:#66d9ef">case</span> x +<span style="color:#66d9ef">when</span> p <span style="color:#66d9ef">then</span> + a +<span style="color:#66d9ef">end</span> +</code></pre></div><h1 id="なぜ普段は書かなくてもよいのか">なぜ普段は書かなくてもよいのか</h1> +<p>普通 Ruby のコードで <code>then</code> を書くことはない。なぜか。次のコードを実行してみるとわかる。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> <span style="color:#66d9ef">true</span> puts <span style="color:#e6db74">'Hello, World!'</span> <span style="color:#66d9ef">end</span> +</code></pre></div><p>次のような構文エラーが出力される。</p> +<pre tabindex="0"><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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> <span style="color:#66d9ef">true</span> +puts <span style="color:#e6db74">'Hello, World!'</span> <span style="color:#66d9ef">end</span> +</code></pre></div><p>無事 Hello, World! と出力されるようになった。</p> +<h1 id="なぜ-then-や--や改行が必要か">なぜ <code>then</code> や <code>;</code> や改行が必要か</h1> +<p>なぜ <code>then</code> や <code>;</code> や改行 (以下 「<code>then</code> 等」) が必要なのだろうか。次の例を見てほしい:</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> a b <span style="color:#66d9ef">end</span> +</code></pre></div><p><code>then</code> も <code>;</code> も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 +この例は二通りに解釈できる。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#75715e"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span> +<span style="color:#66d9ef">if</span> a <span style="color:#66d9ef">then</span> + b +<span style="color:#66d9ef">end</span> +</code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#75715e"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span> +<span style="color:#75715e"># その結果が truthy なら何もしない</span> +<span style="color:#66d9ef">if</span> a(b) <span style="color:#66d9ef">then</span> +<span style="color:#66d9ef">end</span> +</code></pre></div><p><code>then</code> 等はこの曖昧性を排除するためにあり、条件式は <code>if</code> から <code>then</code> 等までの間にある、ということを明確にする。 +C系の <code>if</code> 後に来る <code>(</code>/<code>)</code> や、Python の <code>:</code>、Rust/Go/Swift などの <code>{</code> も同じ役割を持つ。</p> +<p>Ruby の場合、プログラマーが書きやすいよう改行でもって <code>then</code> が代用できるので、ほとんどの場合 <code>then</code> は必要ない。</p> +<h1 id="case---in-における-then"><code>case</code> - <code>in</code> における <code>then</code></h1> +<p>ようやく本題にたどり着いた。来る Ruby 3.0 では <code>case</code> と <code>in</code> キーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとして <code>then</code> 等が必要になる。 +(現在の) Ruby には formal な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc の説明は省略)。</p> +<p><a href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</a></p> +<pre tabindex="0"><code class="language-yacc" 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><p>簡略版:</p> +<pre tabindex="0"><code class="language-yacc" data-lang="yacc">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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">case</span> x +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span> <span style="color:#66d9ef">then</span> a +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">2</span> <span style="color:#66d9ef">then</span> b +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">3</span> <span style="color:#66d9ef">then</span> c +<span style="color:#66d9ef">end</span> + +<span style="color:#66d9ef">case</span> x +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span> + a +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">2</span> + b +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">3</span> + c +<span style="color:#66d9ef">end</span> + +<span style="color:#66d9ef">case</span> x +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span>; a +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">2</span>; b +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">3</span>; c +<span style="color:#66d9ef">end</span> +</code></pre></div><p>ところで、<code>p_top_expr</code> には <code>if</code> による guard clause が書けるので、その場合は <code>if</code> - <code>then</code> と似たような見た目になる。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">case</span> x +<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">then</span> a +<span style="color:#66d9ef">in</span> n <span style="color:#66d9ef">if</span> n <span style="color:#f92672"><</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">then</span> b +<span style="color:#66d9ef">in</span> n <span style="color:#66d9ef">then</span> c +<span style="color:#66d9ef">end</span> +</code></pre></div><h1 id="まとめ">まとめ</h1> +<ul> +<li><code>if</code> や <code>case</code> の条件の後ろには <code>then</code>、<code>;</code>、改行のいずれかが必要 +<ul> +<li>通常は改行しておけばよい</li> +</ul> +</li> +<li>3.0 で入る予定の <code>case</code> - <code>in</code> でも <code>then</code> 等が必要になる</li> +<li>Ruby の構文を正確に知るには (現状) <code>parse.y</code> を直接読めばよい</li> +</ul> +</div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/posts/rust-where-are-primitive-types-from/index.html b/docs/posts/rust-where-are-primitive-types-from/index.html new file mode 100644 index 0000000..d05d19b --- /dev/null +++ b/docs/posts/rust-where-are-primitive-types-from/index.html @@ -0,0 +1,233 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>Rust のプリミティブ型はどこからやって来るか - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/9a429432258bbcd6c565 + 前置き Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 +#![allow(non_camel_case_types)] #![allow(dead_code)] 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; では、普段単に bool と書いたとき、この bool は一体どこから来ているのか。rustc のソースを追ってみた。 + 前提知識: 一般的なコンパイラの構造、用語。rustc そのものの知識は不要 (というよりも筆者自身がよく知らない) + 調査 調査に使用したソース (調査時点での最新 master) +https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98 +どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。 +大雑把な構造としては、compiler フォルダ以下に rustc_* という名前のクレートが数十個入っている。これがどうやら rustc コマンドの実装部のようだ。"> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">Rust のプリミティブ型はどこからやって来るか</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/9a429432258bbcd6c565">https://qiita.com/nsfisis/items/9a429432258bbcd6c565</a></p> +<hr> +<h1 id="前置き">前置き</h1> +<p>Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#75715e">#![allow(non_camel_case_types)]</span> +<span style="color:#75715e">#![allow(dead_code)]</span> + +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">bool</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">char</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i8</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i16</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i32</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i64</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">i128</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">isize</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u8</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u16</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u32</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u64</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">u128</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">usize</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">f32</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">f64</span>; +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">str</span>; +</code></pre></div><p>では、普段単に <code>bool</code> と書いたとき、この <code>bool</code> は一体どこから来ているのか。rustc のソースを追ってみた。</p> +<blockquote> +<p>前提知識: 一般的なコンパイラの構造、用語。<code>rustc</code> そのものの知識は不要 (というよりも筆者自身がよく知らない)</p> +</blockquote> +<h1 id="調査">調査</h1> +<p>調査に使用したソース (調査時点での最新 master)</p> +<p><a 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 tabindex="0"><code>$ git grep "\bi128\b" | wc # i128 + 165 1069 15790 + +$ git grep "\bu128\b" | wc # u128 + 293 2127 26667 + +$ git grep "\bbool\b" | wc # cf. bool の結果 + 3563 23577 294659 +</code></pre><p>165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。</p> +<pre tabindex="0"><code>$ git grep "\bi128\b" +... +rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); +... +</code></pre><p><code>rustc_resolve</code> というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#e6db74">/// Interns the names of the primitive types. +</span><span style="color:#e6db74">/// +</span><span style="color:#e6db74">/// All other types are defined somewhere and possibly imported, but the primitive ones need +</span><span style="color:#e6db74">/// special handling, since they have no place of origin. +</span><span style="color:#e6db74"></span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">PrimitiveTypeTable</span> { + primitive_types: <span style="color:#a6e22e">FxHashMap</span><span style="color:#f92672"><</span>Symbol, PrimTy<span style="color:#f92672">></span>, +} + +<span style="color:#66d9ef">impl</span> PrimitiveTypeTable { + <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">new</span>() -> <span style="color:#a6e22e">PrimitiveTypeTable</span> { + <span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> table <span style="color:#f92672">=</span> FxHashMap::default(); + + table.insert(sym::<span style="color:#66d9ef">bool</span>, Bool); + table.insert(sym::char, Char); + table.insert(sym::<span style="color:#66d9ef">f32</span>, Float(FloatTy::F32)); + table.insert(sym::<span style="color:#66d9ef">f64</span>, Float(FloatTy::F64)); + table.insert(sym::<span style="color:#66d9ef">isize</span>, Int(IntTy::Isize)); + table.insert(sym::<span style="color:#66d9ef">i8</span>, Int(IntTy::I8)); + table.insert(sym::<span style="color:#66d9ef">i16</span>, Int(IntTy::I16)); + table.insert(sym::<span style="color:#66d9ef">i32</span>, Int(IntTy::I32)); + table.insert(sym::<span style="color:#66d9ef">i64</span>, Int(IntTy::I64)); + table.insert(sym::<span style="color:#66d9ef">i128</span>, Int(IntTy::I128)); + table.insert(sym::<span style="color:#66d9ef">str</span>, Str); + table.insert(sym::<span style="color:#66d9ef">usize</span>, Uint(UintTy::Usize)); + table.insert(sym::<span style="color:#66d9ef">u8</span>, Uint(UintTy::U8)); + table.insert(sym::<span style="color:#66d9ef">u16</span>, Uint(UintTy::U16)); + table.insert(sym::<span style="color:#66d9ef">u32</span>, Uint(UintTy::U32)); + table.insert(sym::<span style="color:#66d9ef">u64</span>, Uint(UintTy::U64)); + table.insert(sym::<span style="color:#66d9ef">u128</span>, Uint(UintTy::U128)); + Self { primitive_types: <span style="color:#a6e22e">table</span> } + } +} +</code></pre></div><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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"> <span style="color:#e6db74">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. +</span><span style="color:#e6db74"></span> <span style="color:#e6db74">/// (略) +</span><span style="color:#e6db74"></span> <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">resolve_ident_in_lexical_scope</span>( + <span style="color:#f92672">&</span><span style="color:#66d9ef">mut</span> self, + <span style="color:#66d9ef">mut</span> ident: <span style="color:#a6e22e">Ident</span>, + ns: <span style="color:#a6e22e">Namespace</span>, + <span style="color:#75715e">// (略) +</span><span style="color:#75715e"></span> ) -> Option<span style="color:#f92672"><</span>LexicalScopeBinding<span style="color:#f92672"><</span><span style="color:#a6e22e">'a</span><span style="color:#f92672">>></span> { + <span style="color:#75715e">// (略) +</span><span style="color:#75715e"></span> + <span style="color:#66d9ef">if</span> ns <span style="color:#f92672">==</span> TypeNS { + <span style="color:#66d9ef">if</span> <span style="color:#66d9ef">let</span> Some(prim_ty) <span style="color:#f92672">=</span> self.primitive_type_table.primitive_types.get(<span style="color:#f92672">&</span>ident.name) { + <span style="color:#66d9ef">let</span> binding <span style="color:#f92672">=</span> + (Res::PrimTy(<span style="color:#f92672">*</span>prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root()) + .to_name_binding(self.arenas); + <span style="color:#66d9ef">return</span> Some(LexicalScopeBinding::Item(binding)); + } + } + + None + } +</code></pre></div><p>関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。 +<code>if ns == TypeNS</code> のブロック内では、<code>primitive_type_table</code> (上記の <code>PrimitiveTypeTable::new()</code> で作られた変数) に含まれている識別子 (<code>bool</code>、<code>i32</code> など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。</p> +<p>なお、<code>ns</code> は「名前空間」を示す変数である。Rust における名前空間はC言語におけるそれとほとんど同じで、今探している名前が関数名/変数名なのか型なのかマクロなのかを区別している。この <code>if</code> は、プリミティブ型に解決されるのは型を探しているときだけだ、と言っている。</p> +<p>重要なのは、これが <code>resolve_ident_in_lexical_scope()</code> の最後に書かれている点である。つまり、最初に挙げたプリミティブ型の識別子は、「名前解決の最終段階で」、「他に同名の型が見つかっていなければ」プリミティブ型として解決される。</p> +<p>動作がわかったところで、例として次のコードを考える。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#75715e">#![allow(non_camel_case_types)]</span> + +<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">bool</span>; + +<span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() { + <span style="color:#66d9ef">let</span> _: <span style="color:#66d9ef">bool</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">bool</span>; +} +</code></pre></div><p>ここで <code>main()</code> の <code>bool</code> は <code>struct bool</code> として解決される。なぜなら、プリミティブ型の判定をする前に <code>bool</code> という名前の別の型が見つかるからだ。</p> +<h1 id="まとめ">まとめ</h1> +<p>Rust のプリミティブ型は予約語ではない。名前解決の最終段階で特別扱いされ、他に同名の型が見つかっていなければ対応するプリミティブ型に解決される。</p> +</div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/docs/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html new file mode 100644 index 0000000..670fa20 --- /dev/null +++ b/docs/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -0,0 +1,186 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>[Vim] autocmd events の BufWrite/BufWritePre の違い - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25 + TL; DR 違いはない。ただのエイリアス。 +調査記録 Vim の autocmd events には似通った名前のものがいくつかある。大抵は :help に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 + BufRead/BufReadPost BufWrite/BufWritePre BufAdd/BufCreate このうち、BufAdd/BufCreate に関しては、:help BufCreate に + The BufCreate event is for historic reasons. + とあり、おそらくは BufAdd のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。 + ソースコードへのリンク vim (調査時点での master branch) neovim (上に同じ) + vim のソースコード 以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。 +https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86 +{"BufAdd", EVENT_BUFADD}, {"BufCreate", EVENT_BUFADD}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97 +{"BufRead", EVENT_BUFREADPOST}, {"BufReadCmd", EVENT_BUFREADCMD}, {"BufReadPost", EVENT_BUFREADPOST}, https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105"> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">[Vim] autocmd events の BufWrite/BufWritePre の違い</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/79ab4db8564032de0b25">https://qiita.com/nsfisis/items/79ab4db8564032de0b25</a></p> +<hr> +<h1 id="tl-dr">TL; DR</h1> +<p>違いはない。ただのエイリアス。</p> +<h1 id="調査記録">調査記録</h1> +<p>Vim の autocmd events には似通った名前のものがいくつかある。大抵は <code>:help</code> に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。</p> +<ul> +<li><code>BufRead</code>/<code>BufReadPost</code></li> +<li><code>BufWrite</code>/<code>BufWritePre</code></li> +<li><code>BufAdd</code>/<code>BufCreate</code></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 href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim (調査時点での master branch)</a> +<a href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim (上に同じ)</a></p> +</blockquote> +<h2 id="vim-のソースコード">vim のソースコード</h2> +<p>以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。</p> +<p><a 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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"> {<span style="color:#e6db74">"BufAdd"</span>, EVENT_BUFADD}, + {<span style="color:#e6db74">"BufCreate"</span>, EVENT_BUFADD}, +</code></pre></div><p><a 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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"> {<span style="color:#e6db74">"BufRead"</span>, EVENT_BUFREADPOST}, + {<span style="color:#e6db74">"BufReadCmd"</span>, EVENT_BUFREADCMD}, + {<span style="color:#e6db74">"BufReadPost"</span>, EVENT_BUFREADPOST}, +</code></pre></div><p><a 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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"> {<span style="color:#e6db74">"BufWrite"</span>, EVENT_BUFWRITEPRE}, + {<span style="color:#e6db74">"BufWritePost"</span>, EVENT_BUFWRITEPOST}, + {<span style="color:#e6db74">"BufWritePre"</span>, EVENT_BUFWRITEPRE}, +</code></pre></div><h2 id="neovim-のソースコード">neovim のソースコード</h2> +<p>neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua で書かれている。以下にある通り、はっきり <code>aliases</code> と書かれている。</p> +<p><a 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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-lua" data-lang="lua"> aliases <span style="color:#f92672">=</span> { + BufCreate <span style="color:#f92672">=</span> <span style="color:#e6db74">'BufAdd'</span>, + BufRead <span style="color:#f92672">=</span> <span style="color:#e6db74">'BufReadPost'</span>, + BufWrite <span style="color:#f92672">=</span> <span style="color:#e6db74">'BufWritePre'</span>, + FileEncoding <span style="color:#f92672">=</span> <span style="color:#e6db74">'EncodingChanged'</span>, + }, +</code></pre></div><p>ところで、上では取り上げなかった <code>FileEncoding</code> だが、これは <code>:help FileEncoding</code> にしっかりと書いてある。</p> +<pre tabindex="0"><code> *FileEncoding* +FileEncoding Obsolete. It still works and is equivalent + to |EncodingChanged|. +</code></pre><h2 id="まとめ">まとめ</h2> +<p>記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。</p> +<ul> +<li><code>BufAdd</code>/<code>BufCreate</code> +<ul> +<li>→ <code>BufCreate</code> は歴史的な理由により (“for historic reasons”) 存在しているため、新しい方 (<code>BufAdd</code>) を使う</li> +</ul> +</li> +<li><code>BufRead</code>/<code>BufReadPost</code> +<ul> +<li>→ <code>BufReadPre</code> との対称性のため、あるいは <code>BufWritePost</code> との対称性のため <code>BufReadPost</code> を使う</li> +</ul> +</li> +<li><code>BufWrite</code>/<code>BufWritePre</code> +<ul> +<li>→ <code>BufWritePost</code> との対称性のため、あるいは <code>BufReadPre</code> との対称性のため <code>BufWritePre</code> を使う</li> +</ul> +</li> +<li><code>FileEncoding</code>/<code>EncodingChanged</code> +<ul> +<li>→ <code>FileEncoding</code> は “Obsolete” と明言されているので、<code>EncodingChanged</code> を使う</li> +</ul> +</li> +</ul> +<p>ところでこの調査で知ったのだが、<code>BufRead</code> と <code>BufWrite</code> は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら <code>Pre</code>/<code>Post</code> 付きのものを使った方が分かりやすいだろう。</p> +</div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/posts/vim-swap-order-of-selected-lines/index.html b/docs/posts/vim-swap-order-of-selected-lines/index.html new file mode 100644 index 0000000..03b0a46 --- /dev/null +++ b/docs/posts/vim-swap-order-of-selected-lines/index.html @@ -0,0 +1,199 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>Vimで選択した行の順番を入れ替える - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="この記事は Qiita から移植してきたものです。 元 URL: https://qiita.com/nsfisis/items/4fefb361d9a693803520 + バージョン情報 :version の一部 + 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. + よく紹介されている手法 tac / tail tac や tail -r などの外部コマンドを ! を使って呼び出し、置き換える。 + :h v_! + tac コマンドや tail の -r オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい +:g/^/m0 こちらは外部コマンドに頼らず、Vim の機能のみを使う。g は :global コマンドの、m は :move コマンドの略 +:global コマンドは :[range]global/{pattern}/[command] のように使い、[range] で指定された範囲の行のうち、{pattern} で指定された検索パターンにマッチする行に対して、順番に [command] で指定された Ex コマンドを呼び出す。"> + <meta name="author" content=""> + + <link href="https://nsfisis.github.io/an-old-hope.min.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/style.css" rel="stylesheet"> + <link href="https://nsfisis.github.io/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://nsfisis.github.io/apple-touch-icon.png"> + <link rel="icon" href="https://nsfisis.github.io/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">Vimで選択した行の順番を入れ替える</h1> + <div class="post-meta">October 2, 2021</div> + </header> + <div class="post-content"><p>この記事は Qiita から移植してきたものです。 +元 URL: <a href="https://qiita.com/nsfisis/items/4fefb361d9a693803520">https://qiita.com/nsfisis/items/4fefb361d9a693803520</a></p> +<hr> +<h1 id="バージョン情報">バージョン情報</h1> +<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> +<h1 id="よく紹介されている手法">よく紹介されている手法</h1> +<h2 id="tac--tail"><code>tac</code> / <code>tail</code></h2> +<p><code>tac</code> や <code>tail -r</code> などの外部コマンドを <code>!</code> を使って呼び出し、置き換える。</p> +<blockquote> +<p>:h v_!</p> +</blockquote> +<p><code>tac</code> コマンドや <code>tail</code> の <code>-r</code> オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい</p> +<h2 id="gm0"><code>:g/^/m0</code></h2> +<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> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <<span style="color:#a6e22e">line1</span>>,<<span style="color:#a6e22e">line2</span>><span style="color:#a6e22e">g</span><span style="color:#e6db74">/^/</span><span style="color:#a6e22e">m</span><<span style="color:#a6e22e">line1</span>><span style="color:#ae81ff">-1</span><span style="color:#960050;background-color:#1e0010"> +</span></code></pre></div><p>これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。</p> +<h1 id="gm0-の問題点"><code>:g/^/m0</code> の問題点</h1> +<p><code>:global</code> コマンドは各行に対してマッチングを行う際、現在の検索パターンを上書きしてしまう。<code>^</code> は行の先頭にマッチするため、結果として全ての行がハイライトされてしまう。<code>'hlsearch'</code> オプションを無効にしている場合その限りではないが、その場合でも直前の検索パターンが失われてしまうと <code>n</code> コマンドなどの際に不便である。</p> +<blockquote> +<p>:h @/</p> +</blockquote> +<h1 id="解決策">解決策</h1> +<blockquote> +<p>[2020/9/28追記] +より簡潔な方法を見つけたので次節に追記した</p> +</blockquote> +<p>前述した <code>:Reverse</code> コマンドの定義を少し変えて、次のようにする:</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#66d9ef">function</span>! <span style="color:#a6e22e">s</span>:<span style="color:#a6e22e">reverse_lines</span>(<span style="color:#a6e22e">from</span>, <span style="color:#a6e22e">to</span>) <span style="color:#a6e22e">abort</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#a6e22e">execute</span> <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">"%d,%dg/^/m%d"</span>, <span style="color:#a6e22e">a</span>:<span style="color:#a6e22e">from</span>, <span style="color:#a6e22e">a</span>:<span style="color:#a6e22e">to</span>, <span style="color:#a6e22e">a</span>:<span style="color:#a6e22e">from</span> - <span style="color:#ae81ff">1</span>)<span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">endfunction</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">call</span> <<span style="color:#a6e22e">SID</span>><span style="color:#a6e22e">reverse_lines</span>(<<span style="color:#a6e22e">line1</span>>, <<span style="color:#a6e22e">line2</span>>)<span style="color:#960050;background-color:#1e0010"> +</span></code></pre></div><p>実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。</p> +<p>この理由は、ユーザー定義関数を実行する際は検索パターンが一度保存され、実行が終了したあと復元されるため。結果として検索パターンが <code>^</code> で上書きされることがなくなる。</p> +<p>Vim のヘルプから該当箇所を引用する (強調は筆者による)。</p> +<blockquote> +<p>:h autocmd-searchpat</p> +<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> +</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|. +<strong>Same thing for when invoking a user function.</strong></p> +</blockquote> +<p>この仕様により、<code>:g/^/m0</code> の呼び出しをユーザー定義関数に切り出すことで上述の問題を解決できる。</p> +<h1 id="解決策-改訂版">解決策 (改訂版)</h1> +<blockquote> +<p>[2020/9/28追記] +より簡潔な方法を見つけたため追記する</p> +</blockquote> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">keeppatterns</span> <<span style="color:#a6e22e">line1</span>>,<<span style="color:#a6e22e">line2</span>><span style="color:#a6e22e">g</span><span style="color:#e6db74">/^/</span><span style="color:#a6e22e">m</span><<span style="color:#a6e22e">line1</span>><span style="color:#ae81ff">-1</span><span style="color:#960050;background-color:#1e0010"> +</span></code></pre></div><p>まさにこのための Exコマンド、<code>:keeppatterns</code> が存在する。<code>:keeppatterns {command}</code> のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。</p> +<blockquote> +<p>:h :keeppatterns</p> +</blockquote> +<h1 id="コピペ用再掲">コピペ用再掲</h1> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#75715e">" License: Public Domain</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010"> +</span><span style="color:#960050;background-color:#1e0010"></span> \ <span style="color:#a6e22e">keeppatterns</span> <<span style="color:#a6e22e">line1</span>>,<<span style="color:#a6e22e">line2</span>><span style="color:#a6e22e">g</span><span style="color:#e6db74">/^/</span><span style="color:#a6e22e">m</span><<span style="color:#a6e22e">line1</span>><span style="color:#ae81ff">-1</span><span style="color:#960050;background-color:#1e0010"> +</span></code></pre></div></div> + +</article></main> +<footer class="footer"> + <span>© 2021 <a href="https://nsfisis.github.io">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://nsfisis.github.io/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 049cc19..54f41b5 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -2,15 +2,36 @@ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <url> + <loc>https://nsfisis.github.io/posts/</loc> + <lastmod>2021-10-02T09:39:27+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/rust-where-are-primitive-types-from/</loc> + <lastmod>2021-10-02T09:39:27+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/ruby-then-keyword-and-case-in/</loc> + <lastmod>2021-10-02T09:38:50+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/cpp-you-can-use-keywords-in-attributes/</loc> + <lastmod>2021-10-02T09:38:30+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/ruby-detect-running-implementation/</loc> + <lastmod>2021-10-02T09:37:50+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/vim-swap-order-of-selected-lines/</loc> + <lastmod>2021-10-02T09:37:25+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</loc> + <lastmod>2021-10-02T09:37:12+09:00</lastmod> + </url><url> + <loc>https://nsfisis.github.io/posts/python-unbound-local-error/</loc> + <lastmod>2021-10-02T09:32:37+09:00</lastmod> + </url><url> <loc>https://nsfisis.github.io/</loc> <lastmod>2021-03-31T01:36:49+09:00</lastmod> </url><url> <loc>https://nsfisis.github.io/posts/phperkaigi-2021/</loc> <lastmod>2021-03-30T23:22:40+09:00</lastmod> </url><url> - <loc>https://nsfisis.github.io/posts/</loc> - <lastmod>2021-03-30T23:22:40+09:00</lastmod> - </url><url> <loc>https://nsfisis.github.io/posts/my-first-post/</loc> <lastmod>2021-03-05T23:38:21+09:00</lastmod> </url><url> |
