I want to make a function that has optional arguments.

In python I would do something like this:

def functionName(arg1,arg2=false,arg3=false):
    if arg2:
        #Do stuff with arguments
        #Do stuff without arguments

I have tried doing function FunctionName(arg1,arg2=false,arg3=false), but it just gives me a error saying invalid argument.

How would I do this in vimscript?


Yes, you can take optional arguments in a function. It is not as convenient as python's way of doing it, but this is how you do it:

function FooBar(...) " This is like *args in python
    echom a:0 " a:0 contains an integer which is the number of arguments passed to the function
    echom a:1 " a:1 contains the first argument passed, a:2 contains the second and so on
    echo a:000 " a:000 contains a list of all arguments that were passed to the function

Note that you may only have up to 20 arguments in this fashion.

Relevant help topics:

:help :function
:help function-argument

Late to the party a bit but I didn't see my favorite one:

function! FunctionName(arg1,...)
    let arg2 = get(a:, 1, 0)
    let arg3 = get(a:, 2, 0)

    if arg2
        "Do stuff with arguments"
        "Do stuff without arguments"

in which get(a:, n, default) will get the nth optional argument returning default if it's not present.

  • Oooh that's nice! – joeytwiddle Sep 6 '17 at 1:57
  • 4
    I know this is super old, but just FYI to anyone reading this. You cannot do let a:arg= anymore in vim. You must use something like let l:arg= or just let arg=. See github.com/vim/vim/commit/… – jmzagorski Feb 21 '19 at 18:37
  • Where is a: documented? Is it the same as a:000? – user202729 Apr 8 '20 at 6:46
  • 1
    @user202729 Check out :help internal-variables, there is a bit explaining that scopes like "a:" or "s:" can be used as dictionaries. It's not quite the same as a:000 because that's a list, as such it's zero-indexed and you would need to use get(a:, n-1, default) instead, but other than that you can use it no problem. – phicr Apr 10 '20 at 3:39

This pattern will let you assign meaningful names to each argument, and provide a default value for any arguments that were not provided:

function FunctionName(foo, ...)
  let bar = a:0 >= 1 ? a:1 : 0
  let baz = a:0 >= 2 ? a:2 : 0
  " Code that makes use of a:foo, bar and baz

As pointed out by Boris Brodski:

a:0 counts the number of optional arguments passed

a:1, a:2, ... let us access the optional arguments

The mandatory arguments (just foo in the example above) are not counted

condition ? result_if_true : result_if_false is the conditional (ternary) expression, which evaluates to the second or third term depending on whether the first term was true or not.

So if no third argument is provided, baz will take the default value of 0.

One concern with the above example is that a:foo can only be accessed with the a: prefix, whilst bar and baz can do without a prefix. Since this is not very consistent, you may prefer to pull out all of the arguments into local variables, like so:

function FunctionName(...)
  let foo = a:1                  " Will throw an error if no arg was provided
  let bar = a:0 >= 2 ? a:2 : 0
  let baz = a:0 >= 3 ? a:3 : 0
  " Code that makes use of foo, bar and baz

(Technically, you can use the l: prefix to refer to local variables inside a function, for example l:baz, but this is redundant so I would not recommend it.)

But I do recommend that you use this form whenever possible:

function! s:FunctionName(...)

The ! allows you to redefine your function at runtime (e.g. by reloading the script), and the s: limits the function to script scope. That avoids polluting the global namespace (and risking collision) if your function is only referenced from elsewhere inside the script. It is generally the preferred way to define functions when they do not need to be globally visible. ;-)

  • 1
    a:0 doesn't include the fixed named parameters. a:1 is the first parameter within the ... (Just tested with VIM 8.0) – Boris Brodski Apr 30 '18 at 11:54
  • Thanks @BorisBrodski you're right, good catch. I have corrected the answer. – joeytwiddle May 1 '18 at 14:44

I'm not well versed in vimscript, but this is how I would do it:

function Func(foo, ...)
  if a:0 < 1
    let bar = "Unspecified bar"
    let bar = a:1
  if a:0 < 2
    let baz = "Unspecified baz"
    let baz = a:2

  echo a:foo
  echo bar
  echo baz

You can then call Func("Hello", "World"), and see that it prints "Hello", "World", "Unspecified baz".

This is using the varargs feature of vim functions, which lets you pass an arbitrary number of extra arguments to the function. The arguments are stored in variables which, depending on a:0 (the length of the extra arguments list), either get set to their corresponding argument or a default value.


Since Vim 8.1.1310 Vim also supports real optional function arguments.

However, that means that most vim installation don't support this yet. Also neovim doesn't offer that feature, too.

Example from :help optional-function-argument:

  function Something(key, value = 10)
     echo a:key .. ": " .. a:value
  call Something('empty')   "empty: 10"
  call Something('key', 20) "key: 20"   
  • 1
    Neat. You should expand your answer to give an example so we can grasp quickly what it adds. – Luc Hermitte Nov 21 '19 at 10:53
  • 1
    @LucHermitte I modified my answer accordingly. – radlan Nov 22 '19 at 8:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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