# Defining a macro for printing vectors with SplitList in xparse

please look at the following example:

\documentclass{book}

\usepackage{xparse}
\usepackage{amsmath}

\makeatletter

\NewDocumentCommand{\vv}{ s > { \SplitList { ; } } m }%
{\begin{pmatrix}%
\ProcessList{#2}{\@vv}%
\end{pmatrix}%
\@firstitemtrue}

\newif\if@firstitem
\@firstitemtrue
\NewDocumentCommand{\@vv}{ m }%
{\if@firstitem%
\@firstitemfalse%
\else%
\\%
\fi%
#1}

\makeatother

\begin{document}

The vector is printend wrong:
$$\vv{a;b;c;d;e;f;g}$$

It should look like:
$$\begin{pmatrix} a \\ b \\ c \\ d \\ e \\ f \\ g \end{pmatrix}$$

\end{document}


I tried to define a macro to typeset vectors comfortably. But something went wrong as you can see on the picture.

Any ideas how to solve the problem?

• The \vv command is also used by the \esvect package, by the way. – user31729 Mar 23 '17 at 20:39

## 3 Answers

The \@firstitemfalse command is done within a array cell, which is a group and will never be false outside, so use \global\@firstitemfalse, but a better solution is to use an expl3 approach with \seq at the end of this answer...

\documentclass{book}

\usepackage{xparse}
\usepackage{amsmath}

\makeatletter

\NewDocumentCommand{\vv}{ s > { \SplitList { ; } } m }%
{\begin{pmatrix}%
\ProcessList{#2}{\@vv}%
\end{pmatrix}%
\@firstitemtrue}

\newif\if@firstitem
\@firstitemtrue
\NewDocumentCommand{\@vv}{ m }%
{\if@firstitem%
\global\@firstitemfalse%
\else%
\\%
\fi%
#1}

\makeatother

\begin{document}

The vector is printend wrong:
$$\vv{a;b;c;d;e;f;g}$$

It should look like:
$$\begin{pmatrix} a \\ b \\ c \\ d \\ e \\ f \\ g \end{pmatrix}$$

\end{document}


Alternate solution with 'direct' usage of expl3 features, so there's no need of \if@firstitem at all, since \seq_use:Nn ... {\\} cares for this.

\documentclass{book}

\usepackage{xparse}
\usepackage{amsmath}

\makeatletter

\ExplSyntaxOn

\cs_new:Nn \split_vector_list:n {%
\seq_set_split:Nnn \l_tmpa_seq {;} {#1}
\seq_use:Nn \l_tmpa_seq {\\}
}

\NewDocumentCommand{\vv}{ sm }{%
\begin{pmatrix}%
\split_vector_list:n {#2}
\end{pmatrix}%
}
\ExplSyntaxOff

\begin{document}

The vector is printend wrong:
$$\vv{a;b;c;d;e;f;g}$$

It should look like:
$$\begin{pmatrix} a \\ b \\ c \\ d \\ e \\ f \\ g \end{pmatrix}$$

\end{document}


• +1 for the seq-use version (-1 for the global setting:-) – David Carlisle Mar 23 '17 at 20:54
• @DavidCarlisle: Desparate times require desperate measures ;-) – user31729 Mar 23 '17 at 20:56
• Thank you. I tried your first solution. I had to add \global also in the definition of the macro to make it work properly mor than once. :) – Weißer Kater Mar 23 '17 at 20:56
• The second solution seems to be very clever but I don't know how to use the ExplSyntax. I tried to read the Manual but I did not help. Do you know another source to learn it? – Weißer Kater Mar 23 '17 at 20:58
• @user125730: The interface3 manual is rather a reference than a description how to use expl3. There is no clear introduction yet. – user31729 Mar 24 '17 at 13:23

\documentclass{book}

\usepackage{xparse}
\usepackage{amsmath}

\makeatletter

\NewDocumentCommand{\vv}{ s > { \SplitList { ; } } m }%
{\begin{pmatrix}%
\ProcessList{#2}{\@vv}%
\end{pmatrix}%
\@firstitemtrue}

\newif\if@firstitem
\@firstitemtrue
\NewDocumentCommand{\@vv}{ m }%
{#1\\}

\makeatother

\begin{document}

The vector is printend wrong:
$$\vv{a;b;c;d;e;f;g}$$

\end{document}


each table cell is a local group so your boolean flag setting was being lost as soon as you did \\

• Oh, I did not know that each table cell is a local group. Thank you. – Weißer Kater Mar 23 '17 at 20:47

There's no need for a conditional: pmatrix is perfectly happy when the last row ends with \\.

\documentclass{book}

\usepackage{xparse}
\usepackage{amsmath}

\NewDocumentCommand{\vv}{ s > { \SplitList { ; } } m }{%
\begin{pmatrix}%
\ProcessList{#2}{\innervv}%
\end{pmatrix}%
}

\NewDocumentCommand{\innervv}{ m }{#1\\}

\begin{document}

$$\vv{a;b;c;d;e;f;g} = \begin{pmatrix} a \\ b \\ c \\ d \\ e \\ f \\ g \end{pmatrix}$$

\end{document}


If the *-variant is meant for printing row vectors, then you have a small problem, so a different strategy is needed: first, split the argument at the first ;, then apply \SplitList to the second part (if it exists). However this would require too many macros.

An approach based on expl3 is therefore preferable:

\documentclass{book}

\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn
\NewDocumentCommand{\vv}{ sm }
{
\IfBooleanTF{#1}
{ \vv_rowcol:nn { #2 } { & } }  % row vector
{ \vv_rowcol:nn { #2 } { \\ } } % column vector
}
\cs_new_protected:Nn \vv_rowcol:nn
{
\begin{pmatrix}
% split the input at semicolons
\seq_set_split:Nnn \l_vv_rowcol_seq { ; } { #1 }
% deliver the items separated by & or \\
\seq_use:Nn \l_vv_rowcol_seq { #2 }
\end{pmatrix}
}
\seq_new:N \l_vv_rowcol_seq
\ExplSyntaxOff

\begin{document}

$$\vv{a;b;c;d;e;f;g} = \begin{pmatrix} a \\ b \\ c \\ d \\ e \\ f \\ g \end{pmatrix}$$

$$\vv*{a;b;c;d;e;f;g} = \begin{pmatrix} a & b & c & d & e & f & g \end{pmatrix}$$

\end{document}
`