Vim script の funcref() を用いても関数の closure を使用するべきではない
タイトルがすでに結論なのですが、この前追加された funcref()
を使用することで、以下のような問題を回避することが出来ます。
function! Foo() let x = 0 function! Bar() closure let x += 1 return x endfunction " return function('Bar') " function() ではなくて funcref() を使用することで " 関数が上書きされた場合の問題を回避する return funcref('Bar') endfunction let F = Foo() echo F() " => 1 echo F() " => 2 echo F() " => 3 " Bar() 関数が書き換えられても問題ない let F2 = Foo() " F() はそのまま動作する echo F() " => 4 echo F2() " => 1 echo F() " => 5
ではこれで問題ないのか?
確かに funcref()
を使用することで問題になっていたコードは意図した動作をするようになりました。
しかし、 funcref()
を利用しても依然として、
- 関数外で参照できる関数を定義してしまう
- 既存の関数を上書きしてしまう
と、いう問題は残ったままです。
斗くんい funcref()
を使用しても『関数を上書きしてしまう』という問題は解決していません。
このような問題が解決しない限りは Vim script でこのような目的の closure は使用するべきではないと個人的に考えています。
Vim script で closure を利用したいのであれば素直にラムダを使うのがよいでしょう。
function! Foo() let x = 0 return { -> [execute("let x += 1"), x][-1] } endfunction let F = Foo() echo F() " => 1