I can't remember start from when and why, i always add ! to function and command:

function! ..

command! ...

But :h E122 says:

            When a function by this name already exists and [!] is
            not used an error message is given.  There is one
            exception: When sourcing a script again, a function
            that was previously defined in that script will be
            silently replaced.
            When [!] is used, an existing function is silently
            replaced.  Unless it is currently being executed, that
            is an error.
            NOTE: Use ! wisely.  If used without care it can cause
            an existing function to be replaced unexpectedly,
            which is hard to debug.

In short, one should use ! only when one need to replace an existing function defined in other scripts. But nothing good would happen if such replace happens, right? So it should be avoided?

I went through a few popular plugins on my machine, all of them use !, even for a script scope function, does that make sense? am i missing something?

  • I’ve been wondering the same thing myself lately, and omitting it in new code hasn’t given me trouble. I think it must be a change—IIRC, in older versions the bang was necessary to allow re-sourcing the file to work – D. Ben Knoble Nov 11 '19 at 13:23
  • 3
    It was changed in 8.1.0515, and in 8.1.0573. FWIW, I've removed the bangs everywhere in my vimrc/plugins and did not notice any issue. The only times where I still have to use a bang, are for functions defined at runtime inside other functions; typically for closures (see :h func-closure). – user938271 Nov 11 '19 at 14:04

When sourcing a script again, a function that was previously defined in that script will be silently replaced.

That's a fairly recent (Vim 8.1) change. Previously, you had to use :function! to redefine an existing function. As plugin writers very frequently reload their scripts during development (as its much faster than restarting Vim and restoring all context), you still see :function! in most plugins, although going forward, this isn't needed any longer.

  • Removing all of these ! would, in some sense, break backwards compat, yes? I regularly have to work on systems where 7.4 is the only version available, and it's inconvenient to drop back a level to edit over scp when I'm already logged in to the system. (I have to use v:val instead of lambdas for exactly this reason.) Might be worth a comment. – D. Ben Knoble Nov 11 '19 at 16:16
  • 2
    @D.BenKnoble: That would only bother contributors that just have an older Vim to work on, and they could resort to restarts or :delfunction. When using a plugin, it (normally) is only sourced once, so no problem. – Ingo Karkat Nov 11 '19 at 18:07

Yes, I also wondered at seeing this topic first time. I suspect that the whole story is due to VimScript version changes, however, personally I still see these points:

  1. As it turns out, for a script-local function there's absolutely no difference between function and function!. Therefore, it becomes rather a matter of taste: some people may prefer "shorter" notation, but writing function! s:myfunc() clearly indicates that this thing is "silently re-sourceable" what I think isn't too bad.

  2. For a global function, there's a small chance of a name clash catching, however many plugins tend to prefer autoloaded functions anyway, and a clash inside your own config is very unlikely.

  3. Sometimes I also like execute()-ing things from a "scratch" buffer. Such stuff must be global and have a "bang" to allow subsequent overwrite.

  4. Just a stupid habit of blindly writing function! and command! (yes, command! should be frowned upon too) ;-)

  • 4 is what i have been doing for a long time. 3 is a good point. – dedowsdi Nov 11 '19 at 23:26

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.