I'm trying to understand the code suggested in https://vi.stackexchange.com/a/28506/6189:

function MyLinks(pat, spat, ssub, sflags) abort
  return glob(a:pat, v:false, v:true)
        \ ->map({_, v -> printf('[%s](%s)', fnamemodify(v, ':t:r')->substitute(a:spat, a:ssub, a:sflags), fnamemodify(v, ':t'))})
        \ ->join("\n")

Parameters are defined MyLinks(pat, spat, ssub, sflags) but when they're used in the function like substitute(a:spat, a:ssub, a:sflags) they're each prefixed with a:.

Why? What's that do?


2 Answers 2


In vim script (vim 8.x and older), a variable can belong to one of a number of scopes. While it's true it's idiosyncratic as no other language has this feature, it's also consistent as no other language has e.g., "buffer variables."

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'ed Vim script.
function-argument  a:     Function argument (only inside a function).
vim-variable       v:     Global, predefined by Vim.

For the most part, you can think of a: as merely a marker for "argument" as they are special (and otherwise ambiguous) in the language's grammar. For instance,

string[a:var]     " index by argument  
string[a : var]   " slice

However, each of these scopes are also exposed as a dictionary so a:['arg'] and a:.arg are also technically valid (but not recommended).

vim9 script introduces def functions, where the prefix is removed. Arguments then behave similarly to python accessible by name alone.

def MyFunc(...itemlist: list<number>)
      for item in itemlist


Having to explicitly write a: to access parameter values while formal parameter names are defined without the a: scope in the function definition is a very old choice. Note: in this case, a: stands for argument. IMO if you really want to know why this choice has been made, you'd better ask on vim-dev mailing. I guess it is needed to distinguish parameters from local variables as l: is the default scope, and unique implicit scope in function definitions.

Note; this behaviour is really unique in vimscripts as elsewhere s:, b:, w: and t: are always mandatory, l: is the default within a function definition (and IIRC, it's explicitly required when used to define a closure), g: is the default outside function definitions (script and command-line level), but required in function definitions.

Later on, the single a: (contrary to a:xxx) has been introduced: it's a dictionary with all the function parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.