vimtricks.wiki Concise Vim tricks, one at a time.

How do I use lambda functions in Vimscript to filter or transform lists?

Answer

{args -> expr}

Explanation

Vim 8.0 introduced lambda expressions — anonymous functions written as {args -> expr} — which make working with lists far more concise. Instead of defining a named function, you pass a lambda directly to filter(), map(), sort(), and similar built-ins.

How it works

The syntax is {argument_list -> return_expression}:

  • {v -> v > 0} — a lambda that returns true if v is positive
  • {i, v -> v * 2} — a lambda receiving index i and value v, returns v * 2
  • The body is a single expression; multi-line logic requires a regular function

When used with filter() and map(), the first argument is the list and the second is the lambda:

filter(list, {i, v -> condition})
map(list, {i, v -> transformation})

Example

" Keep only even numbers
let nums = [1, 2, 3, 4, 5, 6]
let evens = filter(copy(nums), {_, v -> v % 2 == 0})
" evens = [2, 4, 6]

" Double every element
let doubled = map(copy(nums), {_, v -> v * 2})
" doubled = [2, 4, 6, 8, 10, 12]

" Sort strings by length
let words = ['banana', 'fig', 'apple']
call sort(words, {a, b -> len(a) - len(b)})
" words = ['fig', 'apple', 'banana']

Tips

  • filter() and map() modify the list in place — use copy() to preserve the original
  • Use _ as a placeholder for unused index arguments (conventional, not required)
  • Lambdas can capture variables from the enclosing scope with closure: {x -> x + offset} works if offset is defined above
  • funcref('name') creates a first-class reference to a named function — useful as an alternative to lambdas for reusable logic

Next

How do I define a mapping that only takes effect if the key is not already mapped?