while they already exist in the function scope. They remain valid even after
the function returns: >
:function Foo(arg)
: let i = 3
: return {x -> x + i - a:arg}
:endfunction
:let Bar = Foo(4)
:echo Bar(6)
< 5
Note that the variables must exist in the outer scope before the lambda is
defined for this to work. See also |:func-closure|.
Lambda and closure support can be checked with: >
if has('lambda')
Examples for using a lambda expression with |sort()|, |map()| and |filter()|: >
:echo map([1, 2, 3], {idx, val -> val + 1})
< [2, 3, 4] >
:echo sort([3,7,2,1,4], {a, b -> a - b})
< [1, 2, 3, 4, 7]
The lambda expression is also useful for jobs and timers: >
:let timer = timer_start(500,
\ {-> execute("echo 'Handler called'", "")},
\ {'repeat': 3})
< Handler called
Handler called
Handler called
Note that it is possible to cause memory to be used and not freed if the
closure is referenced by the context it depends on: >
function Function()
let x = 0
let F = {-> x}
endfunction
The closure uses "x" from the function scope, and "F" in that same scope
refers to the closure. This cycle results in the memory not being freed.
Recommendation: don't do this.
Notice how execute() is used to execute an Ex command. That's ugly though.
Lambda expressions have internal names like '<lambda>42'. If you get an error
for a lambda expression, you can find what it is with the following command: >
:function <lambda>42
See also: |numbered-function|
==============================================================================
3. Internal variable *internal-variables* *E461*
An internal variable name can be made up of letters, digits and '_'. But it
cannot start with a digit. It's also possible to use curly braces, see
|curly-braces-names|.
An internal variable is created with the ":let" command |:let|.
An internal variable is explicitly destroyed with the ":unlet" command
|:unlet|.
Using a name that is not an internal variable or refers to a variable that has
been destroyed results in an error.
*variable-scope*
There are several name spaces for variables. Which one is to be used is
specified by what is prepended:
(nothing) In a function: local to a function; otherwise: global
|buffer-variable| b: Local to the current buffer.
|window-variable| w: Local to the current window.
|tabpage-variable| t: Local to the current tab page.
|global-variable| g: Global.
|local-variable| l: Local to a function.
|script-variable| s: Local to a |:source|d Vim script.
|function-argument| a: Function argument (only inside a function).
|vim-variable| v: Global, predefined by Vim.
The scope name by itself can be used as a |Dictionary|. For example, to
delete all script-local variables: >
:for k in keys(s:)
: unlet s:[k]
:endfor
<
*buffer-variable* *b:var* *b:*
A variable name that is preceded with "b:" is local to the current buffer.
Thus you can have several "b:foo" variables, one for each buffer.
This kind of variable is deleted when the buffer is wiped out or deleted with
|:bdelete|.
One local buffer variable is predefined:
*b:changedtick* *changetick*
b:changedtick The total number of changes to the current buffer. It is
incremented for each change. An undo command is also a change
in this case. Resetting 'modified' when writing the buffer is
also counted.
This can be used to perform an action only when the buffer has
changed. Example: >
:if my_changedtick != b:changedtick
: let my_changedtick = b:changedtick
: call My_Update()
:endif
< You cannot change or delete the b:changedtick variable.
*window-variable* *w:var* *w:*
A variable name that is preceded with "w:" is local to the current window. It
is deleted when the window is closed.
*tabpage-variable* *t:var* *t:*
A variable name that is preceded with "t:" is local to the current tab page,
It is deleted when the tab page is closed.
*global-variable*