Note to future readers: at the moment of writing this post, a new, faster version of Vimscript is in the works. This post is about the older pre-Vim9 version.

Did you know Vimscript supports closures? It does, see :h func-closure for the details. For example:

function Func1(x)

function! Func1Clos(y) closure

return a:x + a:y

endfunction

return funcref('Func1Clos')

endfunction

But there’s something I find gross about how they work. After Func1 is first executed, Func1Clos will be defined in the global scope as well! And you need to declare Func1Clos with function! because it seems to be redefined every time Func1 is invoked. As I said, gross.

One alternative is to use lambdas (see :h lamdba ) which are anonymous:

function Func2(x)

return { y -> a:x + y }

endfunction

One problem with Vimscript lambdas is that they must return an expression. If you want complex logic that requires defining new variables or invoking statements, you are out of luck.

A third solution is to delegate to a partially applied — see the {arglist} parameter in :h funcref() — auxiliary named function:

function Func3(x)

return funcref('Func3Clos',[a:x])

endfunction function Func3Clos(x,y)

return a:x + a:y

endfunction

This solution at least makes the scope of the auxiliary function clearer.

I’m planning to write Vimscript code that will create a whole lot of closures, so I’m worried about potential performance differences between the three approaches. I wrote this — very naive! — microbenchmark:

function TestFunc(f,rounds)

let i = 0

let time1 = reltime()

while l:i < a:rounds

call a:f(1)(2)

let l:i+=1

endwhile

return reltime(l:time1)

endfunction

So, what are the results?

:echo reltimestr(TestFunc(funcref('Func1'),100000))

1.643

:echo reltimestr(TestFunc(funcref('Func2'),100000))

1.387

:echo reltimestr(TestFunc(funcref('Func3'),100000))

1.326

Lambdas are faster than named function closures, and partially applied auxiliary functions are a bit faster than lambdas.

Edit. it seems that the cost of parsing might play a part. The documentation for Vim9 says this about old-style Vimscript: