Reputation: 5075
I am creating a dynamic function at runtime inside an execute/eval
'd string. The function is built from different variables present at the time the generator function is called. The generator function is below,
function! NewCallback(method, opts)
let my_opts = a:opts
let function_name = "g:MyDynamicFunction_" . a:method
let body = "function! " . function_name . "(...)\n"
let body .= " echo 'running " . function_name . "'\n"
let body .= " echo my_opts\n"
let body .= "endfunction"
execute body
return function_name
endfunction
I am using this function like below. First I create a callback which gives the name of the function generated as a result. I then call this function with :call.
let callback = NewCallback('foo', { 'a': 1, 'b': 2 })
execute(":call " . callback . "(1, 2, 3)")
The problem I am having is accessing variables in the scope of NewCallback inside the generated function. Here I need to access my_opts
which is local to NewCallback
inside the generated function MyDynamicFunction_foo
.
Currently it gives me undefined variable my_ops
Is there a way to do this in viml. ie:- Defining closure functions that can access parent scope?
Thanks.
Upvotes: 4
Views: 672
Reputation: 2374
You can have something like closures in vimscript. They're called dictionary functions. Those are functions associated to a dictionary acting like an implicit context for them. Within those functions, implicit context can be accesed through the keyword self
. So, they're just like object methods. See here for a better explanation.
Using them, you can code your sample like this, for example:
function! NewListener(method, opts)
let context = {'name': a:method, 'opts': a:opts}
function! context.f(...)
echo "running " . self.name . "\n"
echo self.opts
echo "\n"
endfunction
return context
endfunction
let listener = NewListener('foo', { 'a': 1, 'b': 2 })
call listener.f(1, 2, 3)
Upvotes: 6