3

In Vimscript, if you use a function as an R-value, then the function simply evaluates. For example:

let count_pattern += str2nr( strpart( execute( command ), 1 ) )

However, if a function is used by itself then a "call" keyword must be used:

call substitute( current_line, '\d\+', '\=add( listValues, submatch(0) )', 'g')

What is the necessity for the use of the "call" keyword? In most languages one can simply use a function by itself as a statement, but apparently in Vimscript you cannot. Why is this?

4

IMO, we have to consider that vi and ed had ex-commands, and that vim introduces functions.

When vim interprets a line, it needs a way to distinguish :substitute from substitute(), or :MyUserThing (which is a command) from MyUserThing() (which is a function).

That's why :call is required. As :let, this is an ex-command. The difference between these two is that the result will be ignored as we don't need it, but this is anecdotal. What's important is to be able to distinguish ex-commands from function calls.

  • Ahh. So, in the question of OP, the "functions" in the R-value is not a function call in the first place, rather they're ex commands? Or is it that these are actually functions but when used in R-value, they act as ex commands? – klaus Mar 13 at 17:15
  • @klaus The OP was wondering why he couldn't write :substitute( current_line, '\d\+', '\=add( listValues, submatch(0) )', 'g') without the :call. The reason is likely that Vim has no way to know that the end-user wants to call a function and not a command with (whatever) as command parameter. :call is required to remove the ambiguity. – Luc Hermitte Mar 13 at 17:20
  • But couldn't that be made unambiguous by checking out that substitute has () after it? And my query was in let count_pattern += str2nr( strpart( execute( command ), 1 ) ), is execute(command) a function call or an ex command? – klaus Mar 13 at 17:38
  • 1
    @klaus No because (whatever) could be a perfect parameter for a command. – Luc Hermitte Mar 13 at 17:43
  • @klaus, the ex-command is :let here. What is after the equal sign is an expression. – Luc Hermitte Mar 13 at 17:44
3

Hypothesis: When you're using a function as an R-value, or right hand side value, of an assignment statement, you're trying to assign the output of the R-value to the L-value variable.

Why call is needed when calling a function: From the documentation (see :h call) it is evident that call will discard the return value of a function.

                                        *:cal* *:call* *E107* *E117*
:[range]cal[l] {name}([arguments])
        Call a function.  The name of the function and its arguments
        are as specified with |:function|.  Up to 20 arguments can be
        used.  The returned value is discarded.

So, since when you're using functions as R-value you don't want to discard the output of the function, rather want to assign it to the L-value, you don't use call.

Moreover, you don't always need call to call a function. You can pass the function to another function for example,

:function GetMeow()
:  return "Meow String!"
:endfunction
:GetMeow()       " ERROR!
:call GetMeow()  " no output
:echom GetMeow() " shows the string

Edit

Many languages have the notion of "statements" and "expressions" and programs are generally sequences of statements. In C, GetMeow() may be an expression but GetMeow(); (with a semicolon) is a statement. In vim, GetMeow() is an expression but call GetMeow() is a statement, which are referred to as ex commands. It's really not as strange as the question implies.

  • GetMeow() example is from Learn Vimscript The Hard Way by the way. – klaus Mar 9 at 6:08
  • 1
    vimscript is a sequence of (ex) commands, not expressions, and only some of these commands interpret expressions (call, echom, let, etc). I see new users frequently confused by why say, :set option=g:value or :buffer g:buf won't work. some commands like execute and echo are even capable of interpreting multiple expressions: e.g., echo 1 + 2 3 + 4 is well formed – Mass Mar 9 at 15:34
  • I don't understand. Did I leave something out of my answer? Or is there a mistake? You can edit the answer if you want. – klaus Mar 9 at 16:08
  • 1
    I don't really see how the quoted documentation for :call explains why :GetMeow() is an error. From my understanding, it's the latter that the question is really about. @Mass's comment seems to touch on the reasoning, but could do with some fleshing out before becoming a full answer (or possibly integrated into this one). – 8bittree Mar 12 at 19:22
  • @klaus, Although your answer is factual, I felt like it did not address a critical distinction. Many languages have the notion of "statements" and "expressions" and programs are generally sequences of statements. In C, GetMeow() may be an expression but GetMeow(); (with a semicolon) is a statement. In vim, GetMeow() is an expression but call GetMeow() is a statement, which are referred to as ex commands. It's really not as strange as the question implies. – Mass Mar 12 at 19:37

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.