# Apply command to list of elements separated by \and

I am trying to build a command similar to the \author command. It takes one argument with is actually a list of arguments separated by \and. The command needs to apply another command like \underline or \emph to each element of the list. My current approach is

\documentclass{minimal}
\newcommand{\mylist}[1]{%
\def\and{\noexpand\endgroup \noexpand\underline\noexpand\begingroup}%
\edef\myinternallist{\noexpand\underline\noexpand\begingroup #1\noexpand\endgroup}%
\show\myinternallist%
\myinternallist%
}
\begin{document}
\mylist{Element1 \and Element2}
\end{document}


and \show\myinternallist yields

> \myinternallist=macro:
->\underline \begingroup Element1 \endgroup \underline \begingroup Element2\endgroup .


which looks ok to my untrained eye. However, the above code does'nt compile and I have no clue why it does'nt. The expected result looks like this:

-
First of all, \underline\begingroup abc\endgroup is illegal: you can't use \begingroup and \endgroup for delimiting the argument to a macro. –  egreg Apr 25 at 10:11
What do I have to use instead? As I said above, I am not that experienced. –  porst17 Apr 25 at 10:13
There are various tools in etoolbox or expl3. –  egreg Apr 25 at 10:14

You indeed get

\underline \begingroup Element1 \endgroup \underline \begingroup Element2\endgroup


but unfortunately \underline\begingroup Element1 \endgroup is illegal, because \begingroup and \endgroup can't be used for delimiting a macro argument.

There are various tools for this; I'll show a solution based on expl3, the programming layer of the future LaTeX3.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\mylist}{ O{\underline} m }
{
% transfer control to an internal function
\porst_mylist:nn { #1 } { #2 }
}

\seq_new:N \l__porst_list_items_seq
\seq_new:N \l__porst_list_output_seq

\cs_new_protected:Npn \porst_mylist:nn #1 #2
{
% clear the output sequence
\seq_clear:N \l__porst_list_output_seq
% split the input at \and
\seq_set_split:Nnn \l__porst_list_items_seq { \and } { #2 }
% append each item to the output sequence
\seq_map_inline:Nn \l__porst_list_items_seq
{
% #1 is the given argument, ##1 represents the current item
\seq_put_right:Nn \l__porst_list_output_seq { #1 { ##1 } }
}
% output the sequence with something between items
}
\ExplSyntaxOff

\begin{document}

\mylist{Element1 \and Element2}

\mylist[\emph]{Element1 \and Element2}

\end{document}


The first step is splitting the input at the \and tokens; trailing and leading spaces will be removed; the second step is storing the “formatted” items in another sequence, for using this one with some separator between the items.

Another possible tool is etoolbox; but, as you see, it's much more complicated.

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\DeclareListParser*{\andlist@do}{\and}
\newcommand{\andlist@sep}{, }
\newcommand{\mylist}[2][\underline]{%
\def\andlist@output{\@gobble}%
\andlist@do{\andlist@handler{#1}}{#2}%
\andlist@output
}
\appto\nocorrlist{\andlist@sep}

\newcommand{\andlist@handler}[2]{%
\appto\andlist@output{\andlist@sep#1{#2\unskip}}%
}
\makeatother

\begin{document}

\mylist{Element1 \and Element2}

\mylist[\emph]{Element1\and Element2}

\end{document}

-
Would you mind providing a solution with etoolbox as well? I already use the etoolbox package and I would like to avoid loading an additional package like xparse. –  porst17 Apr 25 at 10:31
@porst17 I added it. –  egreg Apr 25 at 10:59
You are right. The expl3 version is much easier to understand. Thanks a lot! –  porst17 Apr 25 at 12:24
@porst17 With etoolbox it's more difficult to remove unwanted spaces and also to insert something only between items. –  egreg Apr 25 at 12:27

If you want a solution not requiring a package, use braces {}, but you'll need balance them in the definition. To hidden them when expanded just use \iffalse .. \fi:

\def\and{\unskip\iffalse{\fi} \noexpand\underline{\iffalse}\fi}%
\protected@edef\myinternallist{\noexpand\underline{#1}}%


\edefcannot be used with arbitrary stuff, so I use \protected@def, which means you must enclose the whole definition with \makatletter .. \makeatother. I've also added \unskip (to remove the space at the end of each block) and a space.

-