From 98682c7a8792e7e79e487fea5024d25cee5aa310 Mon Sep 17 00:00:00 2001
From: nsfisis contained unnecessary whitespaces inside it
---
.../index.html | 12 ++--
.../python-unbound-local-error/index.html | 18 ++----
.../ruby-detect-running-implementation/index.html | 12 ++--
.../ruby-then-keyword-and-case-in/index.html | 68 +++++++---------------
.../rust-where-are-primitive-types-from/index.html | 36 ++++--------
.../index.html | 30 ++++------
.../vim-swap-order-of-selected-lines/index.html | 24 +++-----
7 files changed, 66 insertions(+), 134 deletions(-)
(limited to 'public/posts/2021-10-02')
diff --git a/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html b/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html
index ae44da9..ed91b45 100644
--- a/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html
+++ b/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html
@@ -56,8 +56,7 @@
タイトル落ち。まずはこのコードを見て欲しい。
- #include <iostream>
+ #include <iostream>
[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]
[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]
@@ -75,8 +74,7 @@
// [[using]]
int main() {
std::cout << "Hello, World!" << std::endl;
-}
-
+}
-@@ -126,10 +124,8 @@ std::cout << "Hello, World!" << std::endl; 上のコードでは
-[[using]]をコメントアウトしているが、これはusingキーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。-+// using の例 -[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]] の糖衣構文-// using の例 +[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]] の糖衣構文C++17 の仕様も見てみる (正確には標準化前のドラフト)。 diff --git a/public/posts/2021-10-02/python-unbound-local-error/index.html b/public/posts/2021-10-02/python-unbound-local-error/index.html index 27c2d05..0516d6f 100644 --- a/public/posts/2021-10-02/python-unbound-local-error/index.html +++ b/public/posts/2021-10-02/python-unbound-local-error/index.html @@ -60,15 +60,13 @@ Python でクロージャを作ろうと、次のようなコードを書いた。
--def f(): ++f()def f(): x = 0 def g(): x += 1 g() -f()-関数
-gから 関数fのスコープ内で定義された変数xを参照し、それに 1 を足そうとしている。 これを実行するとx += 1の箇所でエラーが発生する。 @@ -84,8 +82,7 @@ f() local変数xが代入前に参照された、とある。これは、fのxを参照するのではなく、新しく別の変数をg内に作ってしまっているため。 前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。varを変数宣言のための構文として擬似的に利用している。-# 注: var は正しい Python の文法ではない。上記参照のこと ++g()# 注: var は正しい Python の文法ではない。上記参照のこと def f(): var x # f の local変数 'x' を宣言 x = 0 # x に 0 を代入 @@ -94,21 +91,18 @@ var x # g の local変数 'x' を宣言 # たまたま f にも同じ名前の変数があるが、それとは別の変数 x += 1 # x に 1 を加算 (x = x + 1 の糖衣構文) # 加算する前の値を参照しようとするが、まだ代入されていないためエラー -g()-当初の意図を表現するには、次のように書けばよい。
--def f(): ++g()def f(): x = 0 def g(): nonlocal x ## (*) x += 1 -g()--
(*)のように、nonlocalを追加する。これにより一つ外側のスコープ (gの一つ外側 =f) で定義されているxを探しに行くようになる。 diff --git a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html index ed7ccd5..1163674 100644 --- a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -65,14 +65,12 @@ 上記ページの例から引用する:-$ ruby-1.9.1 -ve 'p RUBY_ENGINE' ++"jruby"$ 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 に良い質問と回答があった。 @@ -192,12 +190,10 @@ jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] mruby 該当部分のソースより引用:
--diff --git a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index 9b1df47..ed8d9e8 100644 --- a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -65,20 +65,17 @@ 使われることは稀だが、Ruby では/* ++#define MRUBY_RUBY_ENGINE "mruby"/* * Ruby engine. */ -#define MRUBY_RUBY_ENGINE "mruby"-thenがキーワードになっている。次のように使う: --if cond then ++ endif cond then puts "Y" else puts "N" - end-このキーワードが現れうる場所はいくつかあり、
-if、unless、rescue、case構文がそれに当たる。 上記のように、何か条件を書いた後thenを置き、式がそこで終了していることを示すマーカーとして機能する。-# Example: ++end# Example: if x then a @@ -97,8 +94,7 @@ end case x when p then a -end-@@ -107,21 +103,17 @@ end 普通 Ruby のコードで thenを書くことはない。なぜか。次のコードを実行してみるとわかる。 --+if true puts 'Hello, World!' end-if true puts 'Hello, World!' end次のような構文エラーが出力される。
--20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n' ++ ...f true puts 'Hello, World!' end20: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-二つ目のメッセージは無視して一つ目を読むと、
-thenか;か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。 @@ -131,10 +123,8 @@ end ポイントは改行がthen(や;) の代わりとなることである。trueの後に改行を入れてみる。-+if true -puts 'Hello, World!' end-if true +puts 'Hello, World!' end無事 Hello, World! と出力されるようになった。 @@ -147,27 +137,21 @@ puts 'Hello, World!' end なぜ
-thenや;や改行 (以下 「then等」) が必要なのだろうか。次の例を見てほしい:-+if a b end-if a b end-
thenも;も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。--# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価 ++end# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価 if a then b -end--# a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、 ++end# a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、 # その結果が truthy なら何もしない if a(b) then -end--
then等はこの曖昧性を排除するためにあり、条件式はifからthen等までの間にある、ということを明確にする。 C系のif後に来る(/)や、Python の:、Rust/Go/Swift などの{も同じ役割を持つ。 @@ -188,8 +172,7 @@ end https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986-+ ;p_case_body : keyword_in +-p_case_body : keyword_in { SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); p->command_start = FALSE; @@ -214,17 +197,14 @@ end/*% %*/ /*% ripper: in!($4, $7, escape_Qundef($8)) %*/ } - ;簡略版:
--+p_case_body : keyword_in p_top_expr then compstmt p_cases -;-p_case_body : keyword_in p_top_expr then compstmt p_cases +;ここで、
-keyword_inは文字通りin、p_top_exprはいわゆるパターン、thenはthenキーワードのことではなく、この記事でthen等と呼んでいるもの、つまりthenキーワード、;、改行のいずれかである。 @@ -234,8 +214,7 @@ end これにより、case-whenによる従来の構文と同じように、then等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:-case x ++endcase x in 1 then a in 2 then b in 3 then c @@ -254,20 +233,17 @@ case x in 1; a in 2; b in 3; c -end-ところで、
-p_top_exprにはifによる guard clause が書けるので、その場合はif-thenと似たような見た目になる。-case x ++endcase x in 0 then a in n if n < 0 then b in n then c -end-diff --git a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index 8bcb923..5b1f86a 100644 --- a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -55,8 +55,7 @@ Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 - -#![allow(non_camel_case_types)] ++struct str;#![allow(non_camel_case_types)] #![allow(dead_code)] struct bool; @@ -75,8 +74,7 @@ struct u128; struct usize; struct f32; struct f64; -struct str;-では、普段単に
-boolと書いたとき、このboolは一体どこから来ているのか。rustc のソースを追ってみた。 @@ -111,34 +109,29 @@ struct str;rustcはセルフホストされている (=rustc自身が Rust で書かれている) ので、boolやcharなどで適当に検索をかけてもノイズが多すぎて話にならない。 しかし、お誂え向きなことにi128/u128というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使ってgit grepしてみる。-$ git grep "\bi128\b" | wc # i128 ++3563 23577 294659$ 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-165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。
--$ git grep "\bi128\b" ++...$ git grep "\bi128\b" ... rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); -...--
rustc_resolveというのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。-/// Interns the names of the primitive types. ++}/// Interns the names of the primitive types. /// /// All other types are defined somewhere and possibly imported, but the primitive ones need /// special handling, since they have no place of origin. @@ -169,8 +162,7 @@ table.insert(sym::u64, Uint(UintTy::U64)); table.insert(sym::u128, Uint(UintTy::U128)); Self { primitive_types: table } } -}-これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、 @@ -186,8 +178,7 @@ Self { primitive_types: table } とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。
--/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. ++}/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. /// (略) fn resolve_ident_in_lexical_scope( &mut self, @@ -207,8 +198,7 @@ return Some(LexicalScopeBinding::Item(binding)); } None -}-関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。
-if ns == TypeNSのブロック内では、primitive_type_table(上記のPrimitiveTypeTable::new()で作られた変数) に含まれている識別子 (bool、i32など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。 @@ -226,15 +216,13 @@ None 動作がわかったところで、例として次のコードを考える。-#![allow(non_camel_case_types)] ++}#![allow(non_camel_case_types)] struct bool; fn main() { let _: bool = bool; -}-ここで
-main()のboolはstruct boolとして解決される。なぜなら、プリミティブ型の判定をする前にboolという名前の別の型が見つかるからだ。 diff --git a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index db28b1c..8e34b4d 100644 --- a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -112,30 +112,24 @@ https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86-+{"BufAdd", EVENT_BUFADD}, -{"BufCreate", EVENT_BUFADD},-{"BufAdd", EVENT_BUFADD}, +{"BufCreate", EVENT_BUFADD},https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97
--{"BufRead", EVENT_BUFREADPOST}, ++{"BufReadPost", EVENT_BUFREADPOST},{"BufRead", EVENT_BUFREADPOST}, {"BufReadCmd", EVENT_BUFREADCMD}, -{"BufReadPost", EVENT_BUFREADPOST},-https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105
--{"BufWrite", EVENT_BUFWRITEPRE}, ++{"BufWritePre", EVENT_BUFWRITEPRE},{"BufWrite", EVENT_BUFWRITEPRE}, {"BufWritePost", EVENT_BUFWRITEPOST}, -{"BufWritePre", EVENT_BUFWRITEPRE},-@@ -148,24 +142,20 @@ https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124 - -aliases = { ++},aliases = { BufCreate = 'BufAdd', BufRead = 'BufReadPost', BufWrite = 'BufWritePre', FileEncoding = 'EncodingChanged', -},-ところで、上では取り上げなかった
-FileEncodingだが、これは:help FileEncodingにしっかりと書いてある。-*FileEncoding* ++to |EncodingChanged|.*FileEncoding* FileEncoding Obsolete. It still works and is equivalent -to |EncodingChanged|.-diff --git a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 8a3b304..f4e2b71 100644 --- a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -115,11 +115,9 @@ なお、 :g/^/m0は全ての行を入れ替えるが、:N,Mg/^/mN-1とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。 --command! -bar -range=% ++\ <line1>,<line2>g/^/m<line1>-1command! -bar -range=% \ Reverse -\ <line1>,<line2>g/^/m<line1>-1-これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。 @@ -152,15 +150,13 @@ 前述した
-:Reverseコマンドの定義を少し変えて、次のようにする:-function! s:reverse_lines(from, to) abort ++ \ call <SID>reverse_lines(<line1>, <line2>)function! s:reverse_lines(from, to) abort execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1) endfunction command! -bar -range=% \ Reverse - \ call <SID>reverse_lines(<line1>, <line2>)-実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。 @@ -211,11 +207,9 @@
- command! -bar -range=%
+ command! -bar -range=%
\ Reverse
- \ keeppatterns <line1>,<line2>g/^/m<line1>-1
-
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1
まさにこのための Exコマンド、:keeppatternsが存在する。:keeppatterns {command}のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。
@@ -230,13 +224,11 @@
コピペ用再掲
-
-
" License: Public Domain
+
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1" License: Public Domain
command! -bar -range=%
\ Reverse
- \ keeppatterns <line1>,<line2>g/^/m<line1>-1
-