🌅

新春 Vim クイズ(Vim script における無名関数の名前空間)

2024/01/03に公開

はじめに

新春 Vim クイズのお時間です。

前提知識

Vim script において関数の名前空間は他と別れています。
そのため同名の関数と変数を定義できます。

let s:foo = 0
function s:foo()
  return 1
endfunction

echo s:foo s:foo()

この結果は 0 1 となります。

問題

このスクリプトの出力はどうなるでしょう?

let s:foo = 0
function s:foo() abort
  return 1
endfunction
let s:foo = { -> 2 }
let s:foo = 3

echo s:foo s:foo()

答え

答えを開く

答えは 3 1 となります。

このスクリプトの1行目を削除すると、この部分でエラーが出るようになります。

function s:foo() abort
  return 1
endfunction
let s:foo = { -> 2 }
E705: Variable name conflicts with existing function: s:foo

またこのスクリプトの結果は

let s:foo = 0
let s:foo = { -> 1 }

echo s:foo s:foo()

次のようになります。

function('<lambda>{id}') 1

このことから無名関数を変数に束縛するときは

  • 同名の関数だけが定義されているときは関数扱いになり、関数同士の名前の衝突が起きる
  • 同名の変数が定義されているときは変数扱いになり、変数側を置き換えて関数はそのまま

というロジックになっていることが分かります。

ちなみに次のスクリプトはエラーになります。

let s:foo = { -> 1 }
let s:foo = 0

echo s:foo s:foo()
E1085: Not a callable type: s:foo

同名の変数、関数がどちらも定義されていないときは変数扱いされるようですね。

終わり

今年もよろしくお願いします(新年2本目の記事だけど)

GitHubで編集を提案

Discussion