I propose a different way to cope with what you seem to be doing.
\documentclass[12pt,a4paper]{article}
\usepackage{xparse}
\usepackage{amsmath}
\ExplSyntaxOn
% a general purpose macro for defining other macros
\NewDocumentCommand{\makemultiargument}{mmmmm}
{
\projetmbc_multiarg:nnnnn { #1 } { #2 } { #3 } { #4 } { #5 }
}
% allocate a private variable
\seq_new:N \l__projetmbc_generic_seq
% the internal version of the general purpose macro
\cs_new_protected:Nn \projetmbc_multiarg:nnnnn
{% #1 = separator
% #2 = multiargument
% #3 = code before
% #4 = code between
% #5 = code after
% a group allows nesting
\group_begin:
% split the multiargument into parts
\seq_set_split:Nnn \l__projetmbc_generic_seq { #1 } { #2 }
% execute the <code before>
#3
% deliver the items, with the chosen material between them
\seq_use:Nn \l__projetmbc_generic_seq { #4 }
% execute the <code after>
#5
% end the group started at the beginning
\group_end:
}
\ExplSyntaxOff
% separator: |; before: \begin{pmatrix}; between: \\, after: \end{pmatrix}
\newcommand{\vcoord}[1]{%
\makemultiargument{|}{#1}{\begin{pmatrix}}{\\}{\end{pmatrix}}%
}
\begin{document}
$\vcoord{3 | \vcoord{-4 | -3 } | 0}$
\end{document}

It is possible to add formatting to each entry, with a trailing optional argument (without it the macro is the same as in the previous version).
\documentclass[12pt,a4paper]{article}
\usepackage{xparse}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\makemultiargument}{mmmmmo}
{
\projetmbc_multiarg:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 }
}
\seq_new:N \l__projetmbc_generic_seq
\cs_new_protected:Nn \projetmbc_multiarg:nnnnnn
{% #1 = separator
% #2 = multiargument
% #3 = code before
% #4 = code between
% #5 = code after
% #6 = ornament to items
% allow nesting
\group_begin:
% split the multiargument
\seq_set_split:Nnn \l__projetmbc_generic_seq { #1 } { #2 }
\tl_if_novalue:nF { #6 }
{
\seq_set_eq:NN \l__projetmbc_temp_seq \l__projetmbc_generic_seq
\seq_set_map:NNn \l__projetmbc_generic_seq \l__projetmbc_generic_seq { #6 }
}
#3
\seq_use:Nn \l__projetmbc_generic_seq { #4 }
#5
\group_end:
}
\ExplSyntaxOff
\NewDocumentCommand{\vcoord}{m}
{
\makemultiargument{|}{#1}{\begin{pmatrix}}{\\}{\end{pmatrix}}
}
\NewDocumentCommand{\pboxed}{m}{\boxed{#1}}
\begin{document}
$\vcoord{3 | \vcoord{-4 | -3 } | 0}$
$\makemultiargument{|}{-4 | -3 | 0}{\begin{pmatrix}}{\\}{\end{pmatrix}}[\pboxed{#1}]$
\end{document}
Beware that macros in the trailing argument have to be either fully expandable or protected (which is why I defined \pboxed; the standard \boxed would not fail, but just by chance).

etoolbox(look for\DeclareListParserand\forcsvlist) and of courseexpl3/LaTeX3 has a lot of list parsing/splitting functions going on. – moewe Feb 17 '19 at 07:43\backify's first arg is delimited by|and its second arg is delimited by\@nil. If a delimited arg is nested in braces entirely, these braces will be stripped off. Your\vcoord-macro processes a list of|-delimited arguments. With all elements except the last one, brace-stripping can happen only once, while with the last element brace-stripping can happen twice. As it is relied on\@nilnot being provided by the user, within\vcoordthe sequence|{\@nil}|\@nilcould be attached and instead of checking on the emptiness of#2one could check whether#1=\@nil. – Ulrich Diez Feb 17 '19 at 13:14\vcoord-macro seems to be just an example. It has nice arguments. You can do it with#1\\\backifyas long as cases are excluded where#1consists of tokens that erroneously "eat" the trailing\\\backifyand this way terminate the loop prematurely. – Ulrich Diez Feb 17 '19 at 13:23