Vim Advent Calendar 2013 112日目:Vim script でいろいろな関数の定義方法

この記事は Vim Advent Calendar 2013 112日目の記事になります。
今回は Vim script でのいくつかの関数の定義方法を紹介します。

[グローバル関数]

関数名にはアルファベットと数値と '_' を使用する事ができます。
また、関数名は大文字のアルファベットから始める必要があります。

" どこからでも呼び出す事ができる関数
function! Func()
    echo "global function"
endfunction


ここで定義した関数はどこからでも(コマンドからでも)呼び出すことができます。

[スクリプトローカル関数]

スクリプトローカル関数は定義したスクリプトファイルでのみ呼び出すことができます。
スクリプトローカル関数を定義する場合は関数名を大文字ではなくて s: から始めます。

function! s:func()
    echo "script local function"
endfunction

" 定義したスクリプトファイルからのみ呼び出すことができる
call s:func()


プラグインなどで公開したくない関数を定義する場合に使用します。

[autoload 関数]

autoload 関数は最初に関数が呼び出された時に定義されているスクリプトファイルを読み込み、その後に関数を呼び出します。
これにより『関数が呼び出されるまで関数が定義されているスクリプトファイルは読み込まれない』のでプラグインなどで使用することで起動時間を短くする事ができます。
関数名は {スクリプトファイルのパス} + {任意の関数名} になります。

" autoload/hoge/foo.vim
function! hoge#foo#func()
    echo "autoload/hoge/foo.vim function"
endfunction

" 最初に関数が呼ばれた時に初めて
" autoload/hoge/foo.vim が読み込まれる
call hoge#foo#func()


プラグインなどで公開する関数に使用することが多いです。

[注意]

次のようにグローバル変数g: から初めて設定することができます。

let g:value = 42


同様に関数も g: から始める関数を定義してもエラーにはならないのですが…

" g: から始まる関数名を定義してもエラーにはならない
function! g:func()
    echo "g:func"
endfunction

これはバグです。


もう1度


これはバグです。


将来的に修正される可能性があるので使用しないようにしましょう。
詳細はここら辺を参照して下して下さい。


ちなみに

function! abc:func()
    echo "abc:func"
endfunction

みたいなアグレッシブな関数名も定義することができますが、これも当然バグなのでやめましょう。

[おまけ1]

次のように関数内で関数を定義する事も可能です。

function! Func()
    function! Func2()
        echo "Func2"
    endfunction
    call Func2()
endfunction


この場合はローカル関数が定義される…のではなくてグローバル関数が定義されます。
なので、1度 Func() を呼べばグローバルスコープから Func() を呼ぶことができます。

[おまけ2]

関数内で関数を定義する事ができるので、動的に関数を定義することができます。
これを利用すれば次のように式から関数を生成する関数を作ることができます。

function! Lambda(expr)
    " 式から関数名を sha256() を利用して定義する
    let name = "Lambda_" . sha256(a:expr)
    execute join(["function! " . name . "(...)",
\       "return eval(" . string(a:expr) . ")",
\   "endfunction"], "\n")
    return function(name)
endfunction

echo Lambda("a:1 + a:2")(1, 2)
" => 3

echo Lambda("eval(join(range(a:1), '+'))")(100)
" => 4950


ラムダっぽい。