While playing with map() I get an error, which I cannot understand.

In essense,

pu=map(getcompletion('*','event'), '"h" . v:val')
pu=map(getcompletion('*','event'), "'h' . v:val")
pu=map(getcompletion('*','event'), {i,v -> "h" . v})
pu=map(getcompletion('*','event'), {i,v -> 'h' . v})

only last one works, all other raise error.

I thought it should all work, or it's just not correctly written?


1 Answer 1


What you are seeing here, is essentially the same problem, as why many people struggle with using variables on the command line with the ex commands. See e.g. this question, there are a lot similar ones.

Basically, Vims ex commandline commands expect their arguments to be literal, they cannot contain expressions (like variables or strings). Those commands do handle % and # (and a few others that I do not remember currently) special by replacing the former with the current filename and the latter by the alternate file name. At the same time, " is used to donate the start of a comment, everything after it will be ignored (not even seen by the command). The usage of " as a comment character goes back all the way to the original vi and therefore cannot be changed because this would introduce an incompatibility to the classic vi.

A few commands, that were not available in the original vi implementation, however are able to handle expressions. The help usually mentions whenever a command expects an expression instead of a (literal) argument. The most notable ex commands that do that are :exe, :echo, :echomsg and similar ex commands. That's why one has to use :exe to dynamically build ex commands (see e.g. this answer for a great explanation).

Those expressions can contain variables and strings, either single quoted or double quoted and therefore the " is not detected as the start of a comment there. However, :put is one of the old ex commands that was available already in old original vi. However adding the possibility to put an arbitrary expression using the expression register = has been added for Vim only. So while you can use any expression when using :put=, Vim will still parse the arguments for the :put comments and see " as a start of a comment and not as start of a string.

That is an implementation detail, that can still be seen today.

Note, the error message would have given you a hint:

error message after executing above command

That was me executing your 3rd example:

pu=map(getcompletion('*','event'), {i,v -> "h" . v})

See how the echoed command stops after the -> and does not contain anything after the comment?

That's why you have to escape the " using e.g. \" on the command line for the :put command. So try to use this instead:

:pu =map(getcompletion('*','event'), {i,v -> \"h\" . v})
  • "the " is seen as quote character", well it is a quote character. I think it would be clearer if you described it as "a comment character", which is the case in this context. Also, you mentioned escaping it with \\" but actually you only need a single backslash, \" is enough...
    – filbranden
    Oct 26, 2019 at 8:56
  • A reference to :help :comment is useful here, as it helps explain why using double quotes for strings is fine in many contexts, but not here (I guess it's because it's using the :put command, which is not an exception for the comment semantics of double quotes... Correct?)
    – filbranden
    Oct 26, 2019 at 9:00
  • 2
    the \\" was just me fighting with markdown. Also the current answer is a bit over-simplified. Will update. Oct 26, 2019 at 12:50
  • Awesome expansion!!! 😁
    – filbranden
    Oct 26, 2019 at 15:22

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.