From 0766039bd9e6b9f5e6334e84666f5be698d41fc3 Mon Sep 17 00:00:00 2001
From: nsfisis
#include <iostream>
+ #include <iostream>
-[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]
-[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]
-[[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]]
-[[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]]
-[[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]]
-[[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]]
-[[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]]
-[[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]]
-[[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]]
-[[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]]
-[[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]]
-[[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]]
-[[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]]
-// [[using]]
-int main() {
-std::cout << "Hello, World!" << std::endl;
+[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]
+[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]
+[[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]]
+[[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]]
+[[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]]
+[[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]]
+[[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]]
+[[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]]
+[[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]]
+[[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]]
+[[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]]
+[[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]]
+[[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]]
+// [[using]]
+int main() {
+std::cout << "Hello, World!" << std::endl;
}
@@ -134,8 +134,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 4461af8..1631ccb 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
@@ -10,7 +10,7 @@
【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment | REPL: Rest-Eat-Program Loop
-
+
@@ -70,10 +70,10 @@
Python でクロージャを作ろうと、次のようなコードを書いた。
- def f():
-x = 0
-def g():
-x += 1
+ def f():
+x = 0
+def g():
+x += 1
g()
f()
@@ -92,26 +92,26 @@ f()
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 の糖衣構文)
-# 加算する前の値を参照しようとするが、まだ代入されていないためエラー
+ # 注: 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()
当初の意図を表現するには、次のように書けばよい。
- def f():
-x = 0
-def g():
-nonlocal x ## (*)
-x += 1
+ def f():
+x = 0
+def g():
+nonlocal x ## (*)
+x += 1
g()
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 06b5eb5..03bae40 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
@@ -10,7 +10,7 @@
【Ruby】 自身を実行している処理系の種類を判定する | REPL: Rest-Eat-Program Loop
-
+
@@ -75,10 +75,10 @@
上記ページの例から引用する:
- $ ruby-1.9.1 -ve 'p 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 -ve 'p RUBY_ENGINE'
jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
"jruby"
@@ -200,10 +200,10 @@ jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
mruby 該当部分のソースより引用:
- /*
+ /*
* Ruby engine.
-*/
-#define MRUBY_RUBY_ENGINE "mruby"
+*/
+#define MRUBY_RUBY_ENGINE "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 49127f6..f66ae0b 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
@@ -10,7 +10,7 @@
【Ruby】 then キーワードと case in | REPL: Rest-Eat-Program Loop
-
+
@@ -75,36 +75,36 @@
使われることは稀だが、Ruby ではthenがキーワードになっている。次のように使う:
- if cond then
- puts "Y"
- else
- puts "N"
- end
+ if cond then
+ puts "Y"
+ else
+ puts "N"
+ end
このキーワードが現れうる場所はいくつかあり、if、unless、rescue、case構文がそれに当たる。 上記のように、何か条件を書いた後thenを置き、式がそこで終了していることを示すマーカーとして機能する。
- # Example:
+ # Example:
-if x then
+if x then
a
-end
+end
-unless x then
+unless x then
a
-end
+end
-begin
+begin
a
-rescue then
+rescue then
b
-end
+end
-case x
-when p then
+case x
+when p then
a
-end
+end
@@ -113,17 +113,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'
-if true puts 'Hello, World!' end
+ 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
+20:1: syntax error, unexpected `end', expecting end-of-input
+...f true puts 'Hello, World!' end
二つ目のメッセージは無視して一つ目を読むと、thenか;か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。
@@ -133,8 +133,8 @@ if true puts 'Hello, World!' end
ポイントは改行がthen(や;) の代わりとなることである。trueの後に改行を入れてみる。
- if true
-puts 'Hello, World!' end
+ if true
+puts 'Hello, World!' end
無事 Hello, World! と出力されるようになった。
@@ -147,21 +147,21 @@ puts 'Hello, World!' end
なぜthenや;や改行 (以下 「then等」) が必要なのだろうか。次の例を見てほしい:
- if a b end
+ if a b end
thenも;も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。 この例は二通りに解釈できる。
- # a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
-if a then
+ # a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
+if a then
b
-end
+end
- # a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、
-# その結果が truthy なら何もしない
-if a(b) then
-end
+ # a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、
+# その結果が truthy なら何もしない
+if a(b) then
+end
then等はこの曖昧性を排除するためにあり、条件式はifからthen等までの間にある、ということを明確にする。 C系のif後に来る(/)や、Python の:、Rust/Go/Swift などの{も同じ役割を持つ。
@@ -182,7 +182,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;
@@ -213,7 +213,7 @@ end
簡略版:
- p_case_body : keyword_in p_top_expr then compstmt p_cases
+ p_case_body : keyword_in p_top_expr then compstmt p_cases
;
@@ -224,36 +224,36 @@ end
これにより、case-whenによる従来の構文と同じように、then等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:
- case x
-in 1 then a
-in 2 then b
-in 3 then c
-end
+ case x
+in 1 then a
+in 2 then b
+in 3 then c
+end
-case x
-in 1
+case x
+in 1
a
-in 2
+in 2
b
-in 3
+in 3
c
-end
+end
-case x
-in 1; a
-in 2; b
-in 3; c
-end
+case x
+in 1; a
+in 2; b
+in 3; c
+end
ところで、p_top_exprにはifによる guard clause が書けるので、その場合はif-thenと似たような見た目になる。
- case x
-in 0 then a
-in n if n < 0 then b
-in n then c
-end
+ case 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 e86d724..bc40aaa 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
@@ -10,7 +10,7 @@
Rust のプリミティブ型はどこからやって来るか | REPL: Rest-Eat-Program Loop
-
+
@@ -65,26 +65,26 @@
Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。
- #![allow(non_camel_case_types)]
-#![allow(dead_code)]
+ #![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;
+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 のソースを追ってみた。
@@ -119,20 +119,20 @@ struct str;
rustcはセルフホストされている (=rustc自身が Rust で書かれている) ので、boolやcharなどで適当に検索をかけてもノイズが多すぎて話にならない。 しかし、お誂え向きなことにi128/u128というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使ってgit grepしてみる。
- $ git grep "\bi128\b" | wc # i128
+ $ git grep "\bi128\b" | wc # i128
165 1069 15790
-$ git grep "\bu128\b" | wc # u128
+$ git grep "\bu128\b" | wc # u128
293 2127 26667
-$ git grep "\bbool\b" | wc # cf. bool の結果
+$ 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));
...
@@ -141,36 +141,36 @@ rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));
rustc_resolveというのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。
- /// Interns the names of the primitive types.
-///
-/// All other types are defined somewhere and possibly imported, but the primitive ones need
-/// special handling, since they have no place of origin.
-struct PrimitiveTypeTable {
+ /// Interns the names of the primitive types.
+///
+/// All other types are defined somewhere and possibly imported, but the primitive ones need
+/// special handling, since they have no place of origin.
+struct PrimitiveTypeTable {
primitive_types: FxHashMap<Symbol, PrimTy>,
}
-impl PrimitiveTypeTable {
-fn new() -> PrimitiveTypeTable {
-let mut table = FxHashMap::default();
+impl PrimitiveTypeTable {
+fn new() -> PrimitiveTypeTable {
+let mut table = FxHashMap::default();
-table.insert(sym::bool, Bool);
-table.insert(sym::char, Char);
-table.insert(sym::f32, Float(FloatTy::F32));
-table.insert(sym::f64, Float(FloatTy::F64));
-table.insert(sym::isize, Int(IntTy::Isize));
-table.insert(sym::i8, Int(IntTy::I8));
-table.insert(sym::i16, Int(IntTy::I16));
-table.insert(sym::i32, Int(IntTy::I32));
-table.insert(sym::i64, Int(IntTy::I64));
-table.insert(sym::i128, Int(IntTy::I128));
-table.insert(sym::str, Str);
-table.insert(sym::usize, Uint(UintTy::Usize));
-table.insert(sym::u8, Uint(UintTy::U8));
-table.insert(sym::u16, Uint(UintTy::U16));
-table.insert(sym::u32, Uint(UintTy::U32));
-table.insert(sym::u64, Uint(UintTy::U64));
-table.insert(sym::u128, Uint(UintTy::U128));
-Self { primitive_types: table }
+table.insert(sym::bool, Bool);
+table.insert(sym::char, Char);
+table.insert(sym::f32, Float(FloatTy::F32));
+table.insert(sym::f64, Float(FloatTy::F64));
+table.insert(sym::isize, Int(IntTy::Isize));
+table.insert(sym::i8, Int(IntTy::I8));
+table.insert(sym::i16, Int(IntTy::I16));
+table.insert(sym::i32, Int(IntTy::I32));
+table.insert(sym::i64, Int(IntTy::I64));
+table.insert(sym::i128, Int(IntTy::I128));
+table.insert(sym::str, Str);
+table.insert(sym::usize, Uint(UintTy::Usize));
+table.insert(sym::u8, Uint(UintTy::U8));
+table.insert(sym::u16, Uint(UintTy::U16));
+table.insert(sym::u32, Uint(UintTy::U32));
+table.insert(sym::u64, Uint(UintTy::U64));
+table.insert(sym::u128, Uint(UintTy::U128));
+Self { primitive_types: table }
}
}
@@ -188,26 +188,26 @@ Self { primitive_types: table }
とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。
- /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
-/// (略)
-fn resolve_ident_in_lexical_scope(
-&mut self,
-mut ident: Ident,
+ /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
+/// (略)
+fn resolve_ident_in_lexical_scope(
+&mut self,
+mut ident: Ident,
ns: Namespace,
-// (略)
-) -> Option<LexicalScopeBinding<'a>> {
-// (略)
+// (略)
+) -> Option<LexicalScopeBinding<'a>> {
+// (略)
-if ns == TypeNS {
-if let Some(prim_ty) = self.primitive_type_table.primitive_types.get(&ident.name) {
-let binding =
-(Res::PrimTy(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root())
-.to_name_binding(self.arenas);
-return Some(LexicalScopeBinding::Item(binding));
+if ns == TypeNS {
+if let Some(prim_ty) = self.primitive_type_table.primitive_types.get(&ident.name) {
+let binding =
+(Res::PrimTy(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root())
+.to_name_binding(self.arenas);
+return Some(LexicalScopeBinding::Item(binding));
}
}
-None
+None
}
@@ -226,12 +226,12 @@ None
動作がわかったところで、例として次のコードを考える。
- #![allow(non_camel_case_types)]
+ #![allow(non_camel_case_types)]
-struct bool;
+struct bool;
-fn main() {
-let _: bool = bool;
+fn main() {
+let _: 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 049afdc..f45df6b 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
@@ -10,7 +10,7 @@
【Vim】 autocmd events の BufWrite/BufWritePre の違い | REPL: Rest-Eat-Program Loop
-
+
@@ -122,24 +122,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},
-{"BufReadCmd", EVENT_BUFREADCMD},
-{"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},
-{"BufWritePost", EVENT_BUFWRITEPOST},
-{"BufWritePre", EVENT_BUFWRITEPRE},
+ {"BufWrite", EVENT_BUFWRITEPRE},
+{"BufWritePost", EVENT_BUFWRITEPOST},
+{"BufWritePre", EVENT_BUFWRITEPRE},
@@ -152,11 +152,11 @@
https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124
- aliases = {
-BufCreate = 'BufAdd',
-BufRead = 'BufReadPost',
-BufWrite = 'BufWritePre',
-FileEncoding = 'EncodingChanged',
+ aliases = {
+BufCreate = 'BufAdd',
+BufRead = 'BufReadPost',
+BufWrite = 'BufWritePre',
+FileEncoding = '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 366912c..8dbea05 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
@@ -10,7 +10,7 @@
Vimで選択した行の順番を入れ替える | REPL: Rest-Eat-Program Loop
-
+
@@ -125,7 +125,7 @@
なお、:g/^/m0は全ての行を入れ替えるが、:N,Mg/^/mN-1とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。
- command! -bar -range=%
+ command! -bar -range=%
\ Reverse
\ <line1>,<line2>g/^/m<line1>-1
@@ -160,7 +160,7 @@
前述した:Reverseコマンドの定義を少し変えて、次のようにする:
- function! s:reverse_lines(from, to) abort
+ function! s:reverse_lines(from, to) abort
execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1)
endfunction
@@ -217,7 +217,7 @@
- command! -bar -range=%
+ command! -bar -range=%
\ Reverse
\ keeppatterns <line1>,<line2>g/^/m<line1>-1
@@ -234,7 +234,7 @@
コピペ用再掲
- " License: Public Domain
+ " License: Public Domain
command! -bar -range=%
\ Reverse
--
cgit v1.2.3-70-g09d2