E.g., in this snippet

    if words[0] == "\"spellgood:"
      call remove(words, 0)
      for word in words
        execute "silent spellgood! " . word

taken from "The first and last 5 lines of a file? Use for file specific spell ignore list?"

  • 9
    call calls a function, execute executes an ex command. Feb 22 '16 at 18:49
  • Can you please elaborate and make this into an answer? Credit where credit is due.
    – Yossi Gil
    Feb 22 '16 at 19:13
  • 1
    I try to avoid posting answers these days, because I disagree with SE's new licence policy. As for call vs. execute, you can get more information from the manual: :h call(), :h :exe. Feb 22 '16 at 19:28
  • @SatoKatsura wasn't the policy change postponed? And doesn't the new policy only affect code? I'd say your answer wouldn't have much code in it in this case?
    – muru
    Feb 23 '16 at 0:21
  • 1
    @muru The fact that this issue exists to begin with is ample proof that some level of mutual trust between SE and regular posters needs to be re-established. In my book, the way the issue was handled by SE is not conductive to that. I don't know about you, but posting to SE is not exactly the goal of my life. I'd say SE needs reasonably qualified posters, rather than the other way around. shrug Feb 23 '16 at 9:42

As described in :help call, call is for invoking a built-in or user-defined function. It's useful to use call if you're invoking a function without the intention of capturing the return value, because of how vim's scripting works. That is, if you have a function foo that returns an integer, you must:

call foo()

to call foo without caring about the result, whereas:

let result = foo()

can be used to call foo and put the result in result. Note how call is not required for the second example. call also can take a range, which has the effect of invoking the function for every line in that range, usually.

:help execute, on the other hands, reveals that execute is for evaluating strings as Ex commands. Normally you don't need to use execute in vim scripts, as most of what you type in them is interpreted as an Ex command. However, execute exists and is particularly useful for invoking commands built up at runtime, as was done in the answer you linked to in order to add a word discovered at runtime to the spelling dictionary.

  • 5
    Looking at it from another perspective: vimscript only runs commands. There's no way to directly run a function. You can use the call command if you want to discard the return value, echo if you want up print it, let if you want to save it, but you have to use a command.
    – muru
    Feb 24 '16 at 8:58

Petrie's answer is only partially true.

By partially I mean, take for example, bdelete. Supposedly, as stated by vim's manual, it states that by providing a number N identifying a buffer (as in using the number provided by ls or ls!), you can delete a buffer in vimscript. Well that is only true, if you provide a literal number, like bdelete 6, you will delete buffer 6. However, if you pass a variable to bdelete that contains the buffer number to delete like, bdelete g:buffer_to_delete (where g:buffer_to_delete=6), it will not work! In fact in vimscript you can not write :bdelete g:buffer_to_delete or call bdelete g:buffer_t_delete. However, you can treat the command as a string and execute it like so, exec "bdelete".g:buff_to_delete, that will work!

Thus vimscript call DOES NOT invoke user-defined or internal functions all the time. There are situations where exec must be used because call doesn't function as it is supposed to. This situation has been around for many years and still lingers today with vim 8.0. So be aware and follow the rule:

If you can't make the call try executing instead.

It is not clear when you can use call and when you must use exec for I have found the above situation occurring erratically. So start with call then if it fails, exec will work, as of yet I haven't found an instance when it doesn't, fortunately!

Note to Vimscript World: there are other nuances like the above that should be spelled out clearly in the vim documentation, or at least fixed in the vim code! I and many others I know have spent many many hours in years passed wasting time figuring out these nuances. I thought Emacs was truly terrible in this regard, but Vim too has its own undisclosed idiosyncrasies.

And before you say it....yes I have provided these issues years ago. I am only writing this now, because I feel a lot of sympathy for Yossi for going through this problem, because I had the same problem many years ago.

Yossi: keep an open mind with Vimscript it lacks quite a bit of common-sense, but if you keep your wits about yourself you can get much for your time spent on vim, than you would with say with Emacs! Trust me, I've been using Emacs and (G)Vi(m) for 30 years now. (G)Vi(m) is the way to go...Emacs is fast dying, and rightly so :-( {Hey Stallman, don't you think its time to admit Emacs sux? Why go to all the trouble and create Evil, when Vim is free?}

Keep pushing Yossi! It will pay off! (Yes everybody, I know this reply is a year late, but I can bet you there are many other Yossi's out there)

Let's hope, Vim 9.0, will do a better job than Vim 8.0. (I hope I will be still alive to see 9.0!)

  • 3
    :call is an Ex command that can only call (sic) functions (user defined, or builtin). We use it when we don't care about the returned value. :execute is an Ex command that can only execute an Ex command. Vim interpreter already executes Ex commands on its own, however it doesn't permit to pass dynamic parameters to these commands. Hence :execute. There is also the call() function that eases dynamic calling of functions (dynamic name, dynamic number of parameters). In a way, call() simplifies what we used to do to forward calls with execute in Vim6 & in prior versions. Jan 30 '17 at 16:15
  • 2
    That is not quite true. call works perfectly fine. Jan 30 '17 at 16:41
  • 1
    IOW, we can't say that :call doesn't do its job. Executing Ex commands is not its job. It's :execute job. I won't say this isn't cumbersome. Fighting with (against?) :exe is really cumbersome. Jan 30 '17 at 16:41
  • 1
    bdelete isn't a function.
    – Rich
    Jan 30 '17 at 17:20
  • 3
    If you can't make the call try executing instead. You really sound like you don't totally understand what you're talking about.
    – statox
    Jan 30 '17 at 17:42

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.