Vim Advent Calendar 2013 の 64 日目の記事です。
Vim script の変数には以下の型があります。
- Number (数値)
- String (文字列)
- Float (浮動小数点数)
- List (リスト)
- Dictionary (辞書)
- Funcref (関数参照)
このうち、String <=> Number 間と Number <=> Float 間では暗黙の型変換が行われます。
ある値が入っている変数に対して、暗黙の型変換が行われない別の型の値を代入しようとするとエラーになります。
" :help sticky-type-checking から抜粋 :let l = "string" :let l = 44 " 型が文字列から数値に変わる :let l = [1, 2, 3] " エラー! l はまだ数値である :let l = 4.4 " 型が数値から浮動小数点数に変わる :let l = "string" " エラー!
まず、String <=> Float が変換されないので、入れる順番によってエラーになったりならなかったりします。キモい。
let a = "foo" let a = 10 let a = 3.14 " OK let b = "foo" let b = 3.14 " エラー!
このエラーを避けるためには、一旦 :unlet する必要があります。特に for で複数の型が入っているリストを回す場合は注意が必要です。
for var in [1, [], "string"] echo var unlet var " unlet がないと型が違うためループ時にエラーになる endfor
更にキモいのは、辞書のメンバー変数に対して代入する時には適用されない点です。
let dict = {} let dict.var = "foo" let dict.var = 3.14 " OK! let dict.var = [] " OK!!!
これと、g: や l: が辞書変数であることを利用すると、以下のような hack が可能です。
let g:foo = "hoge\nhuga" " これを split した配列に置き換えたい " let g:foo = split(g:foo, "\n") " これは当然エラー " 普通にやるとこう let g:foo_temp = split(g:foo, "\n") unlet g:foo let g:foo = g:foo_temp unlet g:foo_temp " hack " g: はグローバル変数が全て入った辞書であり、その辞書の .foo 要素に対して値を代入している let g:.foo = split(g:foo, "\n")
便利。…だけど…キモい。