読者です 読者をやめる 読者になる 読者になる

Vim script の lambda で execute() を使うとローカル変数がキャプチャされない

さて、Vim script の lambda 内でローカル変数を使用すると自動的にキャプチャが行われます。

function! s:main()
    let value = 42
    let F = { -> value + value }

    echo F()
   " => 84

    let value = -4
    echo F()
   " => -8
endfunction
call s:main()

lambda 内で execute() を利用すると変数がキャプチャされない

例えば、次のように lambda 内で let を使用したい場合は execute("") を介してコマンドを呼び出します。

echo { -> [execute("let value = 42"), value + value][-1] }()
" => 84

しかし、execute() 内でローカル変数を使用した場合、キャプチャは行われません。

function! s:main()
    let value = 0
    let F = { -> execute("let value += 1") }

   " Error: E121: 未定義の変数です: value
    call F()
endfunction
call s:main()

これは execute() 内で『変数が使用されたかされてないか』とチェックしてないからぽいです。 例えば、次のようにして execute() 外でローカル変数を使用すれば問題なくキャプチャが行われます。

function! s:main()
    let value = 0
    let F = { -> [execute("let value += 1"), value] }

   " OK
    call F()
    call F()
    call F()

   " ローカル変数は書き換えれてる
    echo value
   " => 3
endfunction
call s:main()

意図しない動作ではあるけど、仕様ぽいなあ。