6

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

function! ..
...
endfunction

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?

2
  • 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, 2019 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, 2019 at 14:04

3 Answers 3

7

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.

2
  • 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, 2019 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. Nov 11, 2019 at 18:07
2

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) ;-)

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

This NOTE makes me spend some time searching for a wonderful solution

        NOTE: Use ! wisely.  If used without care it can cause
        an existing function to be replaced unexpectedly,
        which is hard to debug.

I do not use func! in my init.vim. But after saving my init.vim twice, I get E122.

In many places, we can find advice like this:
from https://groups.google.com/g/vim_use/c/Rb1NQVl8fC8/m/ZhXqhDch_1QJ

Put a ! after :function.

To make sure a .vimrc is able to be sourced more than once, you need to do that;

you also should make sure you have ! after each :command you define

and wrap any autocommands in groups something like this:

augroup MyAutoCmds 
au! 
au ... 
au ...
augroup END

So I decide to do this:

Just a stupid habit of blindly writing function! and command!

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.