Vim Script で、apply と lambda

もはや誰得なのかが分からない。
関数型言語はあまり分からないんですが、こんな感じなんでしょうかねぇ。
個人的にやりたい事は出来た気はする。

[ソース]

" ---------------------------------------------------------
function! s:has_apply(dict)
    try
        return has_key(a:dict, "apply")
    catch
        return 0
    endtry
endfunction


" ---------------------------------------------------------
" 関数の評価
function! s:apply(func, ...)
    if a:0 == 0
        return s:has_apply(a:func) ? a:func.apply() : a:func()
    endif
    if a:0 == 1
        return s:has_apply(a:func) ? a:func.apply(a:1) : a:func(a:1)
    endif
    if a:0 == 2
        return s:has_apply(a:func) ? a:func.apply(a:1, a:2) : a:func(a:1, a:2)
    endif
    if a:0 == 3
        return s:has_apply(a:func) ? a:func.apply(a:1, a:2, a:3) : a:func(a:1, a:2, a:3)
    endif
endfunction

" 無名関数の定義
function! s:lambda(lambda)
    let func = { "lambda" : a:lambda }
    function! func.apply(...) dict
        return eval(self.lambda)
    endfunction
    return func
endfunction

" ---------------------------------------------------------
function! s:plus(a, b)
    return a:a + a:b
endfunction

echo s:apply(function("s:plus"), 3, 5)

let minus={}
function! minus.apply(a, b) dict
    return a:a - a:b
endfunction

echo s:apply(minus, 3, 5)

echo s:lambda("a:1 + a:2").apply(2, 5)
echo s:apply(s:lambda("a:2 - a:1"), 6, 2)
echo s:apply(s:lambda("len(a:1)"), [1, 2, 3])

[出力]

8
-2
7
-4
3

apply は、可変長引数をそのまま別の関数に渡せなかったので、無理やり展開しています。
引数は3つまでしか対応していないけど、まぁしょうが無い。
lambda は、eval 関数を使用して評価しています。
a:1 や a:2 は引数の数そのままですね。
ただし、lambda 内で、ローカル変数が使えないのがちょっとネック。
使用する場合は、辞書型で渡すしかないかなー。