From 4681e861efcdf9b0b73e3803e70712bc55162863 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 8 Aug 2026 10:38:18 +0900 Subject: feat(slides): improve slide controller --- .../index.html | 60 +++--- .../python-unbound-local-error/index.html | 51 +++--- .../ruby-detect-running-implementation/index.html | 45 ++--- .../ruby-then-keyword-and-case-in/index.html | 204 +++++++++++---------- .../rust-where-are-primitive-types-from/index.html | 199 ++++++++++---------- .../index.html | 41 +++-- .../vim-swap-order-of-selected-lines/index.html | 42 +++-- 7 files changed, 340 insertions(+), 302 deletions(-) (limited to 'services/nuldoc/public/blog/posts/2021-10-02') diff --git a/services/nuldoc/public/blog/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html b/services/nuldoc/public/blog/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html index db3f0334..ea909c94 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html @@ -15,7 +15,7 @@ 【C++】 属性構文の属性名にはキーワードが使える|REPL: Rest-Eat-Program Loop - +
@@ -72,41 +72,44 @@ タイトル落ち。まずはこのコードを見て欲しい。

-
#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; -
}
+
#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;
+}
+

コンパイラのバージョン

-
$ 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
+
$ 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
+

コンパイルコマンド (C++17 指定)

-
$ clang --std=c++17 hoge.cpp
+
$ clang --std=c++17 hoge.cpp
+

この記事から得られるものはこれ以上ないので以下は蛇足になる。 @@ -136,8 +139,9 @@ 上のコードでは [[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/services/nuldoc/public/blog/posts/2021-10-02/python-unbound-local-error/index.html b/services/nuldoc/public/blog/posts/2021-10-02/python-unbound-local-error/index.html index a38d197c..aa63127f 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/python-unbound-local-error/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/python-unbound-local-error/index.html @@ -15,7 +15,7 @@ 【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment|REPL: Rest-Eat-Program Loop - +

@@ -75,13 +75,14 @@ Python でクロージャを作ろうと、次のようなコードを書いた。

-
def f(): -
x = 0 -
def g(): -
x += 1 -
g() -
-
f()
+
def f():
+    x = 0
+    def g():
+        x += 1
+    g()
+
+f()
+

関数 g から 関数 f のスコープ内で定義された変数 x を参照し、それに 1 を足そうとしている。 これを実行すると x += 1 の箇所でエラーが発生する。 @@ -95,27 +96,29 @@ local変数 x が代入前に参照された、とある。これは、fx を参照するのではなく、新しく別の変数を 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()
+
# 注: 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 -
g()
+
def f():
+    x = 0
+    def g():
+        nonlocal x   ## (*)
+        x += 1
+    g()
+

(*) のように、nonlocal を追加する。これにより一つ外側のスコープ (g の一つ外側 = f) で定義されている x を探しに行くようになる。 diff --git a/services/nuldoc/public/blog/posts/2021-10-02/ruby-detect-running-implementation/index.html b/services/nuldoc/public/blog/posts/2021-10-02/ruby-detect-running-implementation/index.html index 0dfc31fd..c2083d44 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -15,7 +15,7 @@ 【Ruby】 自身を実行している処理系の種類を判定する|REPL: Rest-Eat-Program Loop - +

@@ -81,12 +81,13 @@ 上記ページの例から引用する:

-
$ 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"
+
$ 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 に良い質問と回答があった。 @@ -96,16 +97,17 @@

-
| RUBY_ENGINE | Implementation | -
|:-----------:|:------------------| -
| <undefined> | MRI < 1.9 | -
| 'ruby' | MRI >= 1.9 or REE | -
| 'jruby' | JRuby | -
| 'macruby' | MacRuby | -
| 'rbx' | Rubinius | -
| 'maglev' | MagLev | -
| 'ironruby' | IronRuby | -
| 'cardinal' | Cardinal |
+
| RUBY_ENGINE | Implementation    |
+|:-----------:|:------------------|
+| <undefined> | MRI < 1.9         |
+| 'ruby'      | MRI >= 1.9 or REE |
+| 'jruby'     | JRuby             |
+| 'macruby'   | MacRuby           |
+| 'rbx'       | Rubinius          |
+| 'maglev'    | MagLev            |
+| 'ironruby'  | IronRuby          |
+| 'cardinal'  | Cardinal          |
+

@@ -121,10 +123,11 @@

version.h
-
/* -
* Ruby engine. -
*/ -
#define MRUBY_RUBY_ENGINE "mruby"
+
/*
+ * Ruby engine.
+ */
+#define MRUBY_RUBY_ENGINE  "mruby"
+
diff --git a/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index 8a13a7e2..ce5b34f0 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -15,7 +15,7 @@ 【Ruby】 then キーワードと case in|REPL: Rest-Eat-Program Loop - +
@@ -103,36 +103,38 @@ 使われることは稀だが、Ruby では then がキーワードになっている。次のように使う:

-
if cond then -
puts "Y" -
else -
puts "N" -
end
+
if cond then
+  puts "Y"
+else
+  puts "N"
+end
+

このキーワードが現れうる場所はいくつかあり、ifunlessrescuecase 構文がそれに当たる。 上記のように、何か条件を書いた後 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
+
# Example:
+
+if x then
+  a
+end
+
+unless x then
+  a
+end
+
+begin
+  a
+rescue then
+  b
+end
+
+case x
+when p then
+  a
+end
+
@@ -141,17 +143,19 @@ 普通 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 `end', expecting end-of-input -
...f 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
+

二つ目のメッセージは無視して一つ目を読むと、then; か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。 @@ -160,8 +164,9 @@ ポイントは改行が then (や ;) の代わりとなることである。true の後に改行を入れてみる。

-
if true -
puts 'Hello, World!' end
+
if true
+puts 'Hello, World!' end
+

無事 Hello, World! と出力されるようになった。 @@ -173,22 +178,25 @@ なぜ then; や改行 (以下 「then 等」) が必要なのだろうか。次の例を見てほしい:

-
if a b end
+
if a b end
+

then; も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。この例は二通りに解釈できる。

-
# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価 -
if a then -
b -
end
+
# a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価
+if a then
+b
+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 などの { も同じ役割を持つ。 @@ -209,39 +217,41 @@

parse.y
-
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)) %*/ -
} -
;
+
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)) %*/
+}
+;
+

簡略版:

-
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 は文字通り inp_top_expr はいわゆるパターン、thenthen キーワードのことではなく、この記事で then 等と呼んでいるもの、つまり then キーワード、;、改行のいずれかである。 @@ -250,36 +260,38 @@ これにより、case - when による従来の構文と同じように、then 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:

-
case x -
in 1 then a -
in 2 then b -
in 3 then c -
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
+
case x
+in 1 then a
+in 2 then b
+in 3 then c
+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/services/nuldoc/public/blog/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/services/nuldoc/public/blog/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index cf40ebf7..fea2aab4 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -15,7 +15,7 @@ Rust のプリミティブ型はどこからやって来るか|REPL: Rest-Eat-Program Loop - +
@@ -88,26 +88,27 @@ 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;
+
#![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 のソースを追ってみた。 @@ -134,23 +135,25 @@ rustc はセルフホストされている (= rustc 自身が Rust で書かれている) ので、boolchar などで適当に検索をかけてもノイズが多すぎて話にならない。しかし、お誂え向きなことに i128/u128 というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使って git grep してみる。

-
$ 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
+
$ 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" -
... -
rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); -
...
+
$ git grep "\bi128\b"
+...
+rustc_resolve/src/lib.rs:        table.insert(sym::i128, Int(IntTy::I128));
+...
+

rustc_resolve というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。 @@ -159,72 +162,75 @@

rustc_resolve/src/lib.rs
-
/// 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(); -
-
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 } -
} -
}
+
/// 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();
+
+        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 }
+    }
+}
+

これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、

-
All other types are defined somewhere and possibly imported, but the -
primitive ones need special handling, since they have no place of -
origin.
+
All other types are defined somewhere and possibly imported, but the
+primitive ones need special handling, since they have no place of
+origin.
+

とある。次はこの 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, -
ns: Namespace, -
// (略) -
) -> 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)); -
} -
} -
-
None -
}
+
/// 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>> {
+    // (略)
+
+    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
+}
+

関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。if ns == TypeNS のブロック内では、primitive_type_table (上記の PrimitiveTypeTable::new() で作られた変数) に含まれている識別子 (booli32 など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。 @@ -239,13 +245,14 @@ 動作がわかったところで、例として次のコードを考える。

-
#![allow(non_camel_case_types)] -
-
struct bool; -
-
fn main() { -
let _: bool = bool; -
}
+
#![allow(non_camel_case_types)]
+
+struct bool;
+
+fn main() {
+    let _: bool = bool;
+}
+

ここで main()boolstruct bool として解決される。なぜなら、プリミティブ型の判定をする前に bool という名前の別の型が見つかるからだ。 diff --git a/services/nuldoc/public/blog/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/services/nuldoc/public/blog/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index 301dcfdc..d3b081f7 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -15,7 +15,7 @@ 【Vim】 autocmd events の BufWrite/BufWritePre の違い|REPL: Rest-Eat-Program Loop - +

@@ -146,8 +146,9 @@
src/autocmd.c
-
{"BufAdd", EVENT_BUFADD}, -
{"BufCreate", EVENT_BUFADD},
+
{"BufAdd",      EVENT_BUFADD},
+{"BufCreate",   EVENT_BUFADD},
+

https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97 @@ -156,9 +157,10 @@

src/autocmd.c
-
{"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 @@ -167,9 +169,10 @@

src/autocmd.c
-
{"BufWrite", EVENT_BUFWRITEPRE}, -
{"BufWritePost", EVENT_BUFWRITEPOST}, -
{"BufWritePre", EVENT_BUFWRITEPRE},
+
{"BufWrite",    EVENT_BUFWRITEPRE},
+{"BufWritePost",    EVENT_BUFWRITEPOST},
+{"BufWritePre", EVENT_BUFWRITEPRE},
+
@@ -184,12 +187,13 @@
src/nvim/auevents.lua
-
aliases = { -
BufCreate = 'BufAdd', -
BufRead = 'BufReadPost', -
BufWrite = 'BufWritePre', -
FileEncoding = 'EncodingChanged', -
},
+
aliases = {
+  BufCreate = 'BufAdd',
+  BufRead = 'BufReadPost',
+  BufWrite = 'BufWritePre',
+  FileEncoding = 'EncodingChanged',
+},
+

ところで、上では取り上げなかった FileEncoding だが、これは :help FileEncoding にしっかりと書いてある。 @@ -198,9 +202,10 @@

:help FileEncoding
-
*FileEncoding* -
FileEncoding Obsolete. It still works and is equivalent -
to |EncodingChanged|.
+
                                                              *FileEncoding*
+FileEncoding                    Obsolete.  It still works and is equivalent
+                                to |EncodingChanged|.
+
diff --git a/services/nuldoc/public/blog/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/services/nuldoc/public/blog/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 42a946c2..eb1c34c0 100644 --- a/services/nuldoc/public/blog/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/services/nuldoc/public/blog/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -15,7 +15,7 @@ Vimで選択した行の順番を入れ替える|REPL: Rest-Eat-Program Loop - +
@@ -102,11 +102,12 @@

TL; DR

-
" License: Public Domain -
-
command! -bar -range=% -
\ Reverse -
\ keeppatterns <line1>,<line2>g/^/m<line1>-1
+
" License: Public Domain
+
+command! -bar -range=%
+    \ Reverse
+    \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+
@@ -164,9 +165,10 @@ なお、:g/^/m0 は全ての行を入れ替えるが、:N,Mg/^/mN-1 とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。

-
command! -bar -range=% -
\ Reverse -
\ <line1>,<line2>g/^/m<line1>-1
+
command! -bar -range=%
+    \ Reverse
+    \ <line1>,<line2>g/^/m<line1>-1
+

これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。 @@ -200,13 +202,14 @@ 前述した :Reverse コマンドの定義を少し変えて、次のようにする:

-
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>)
+
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>)
+

実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。 @@ -253,9 +256,10 @@

-
command! -bar -range=% -
\ Reverse -
\ keeppatterns <line1>,<line2>g/^/m<line1>-1
+
command! -bar -range=%
+    \ Reverse
+    \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+

まさにこのための Exコマンド、:keeppatterns が存在する。:keeppatterns {command} のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。 -- cgit v1.3.1