# Mapping a macro onto multiple lists simultaneously

I have a macro (say \myMacro) that takes three arguments (say a, b, c) and I want to write another macro (say \otherMacro) that given three lists of parameters (comma delimited lists and all of the same length and the length of the lists is two or more) maps \myMacro onto these arguments in turn. That is

\otherMacro {a1, a2, a3}{b1, b2, b3}{c1, c2, c3}


gives the representation

\myMacro{a1}{b1}{c1} \mapsto
(\myMacro{a2}{b2}{c2} , \myMacro{a3}{b3}{c3})


and

\otherMacro {a1, a2, a3, a4}{b1, b2, b3, b4}{c1, c2, c3, c4}


gives the representation

\myMacro{a1}{b1}{c1} \mapsto
(\myMacro{a2}{b2}{c2} , \myMacro{a3}{b3}{c3}, \myMacro{a4}{b4}{c4})


I am a LaTeX novice and I am very sorry if similar questions have already been asked. I searched the site and found problems that were somewhat similar but I couldn't make sense of the solutions.

-

A rather crude version:

\documentclass{article}

\makeatletter
\newcount\my@index
\newcommand\otherMacro[3]
{%
\my@index\z@
\@othermacro#1,\@nil#2,\@nil#3,\@nil
}
\def\@othermacro#1,#2\@nil#3,#4\@nil#5,#6\@nil
{%
\ifnum\my@index=\@ne\mapsto (\fi
\ifnum\my@index>\@ne,\fi
\myMacro{#1}{#3}{#5}%
\ifx\empty#2\empty
)%
\else
\@othermacro#2\@nil#4\@nil#6\@nil
\fi
}
\newcommand\myMacro[3]{\max(#1,#2,#3)}
\makeatother

\begin{document}

$\otherMacro {a1,a2,a3,a4}{b1,b2,b3,b4}{c1,c2,c3,c4}$

\end{document}

-
Works perfectly. Thank you so much! – A R Mar 26 '12 at 15:18
In that case you could accept the answer. – Stephan Lehmke Mar 26 '12 at 15:18
@stephen-lehmke Thank you again. I had never seen this syntax before (e.g. \@ne, \my@index, etc.) I was wondering if you could tell me where I can read more about this? – A R Mar 26 '12 at 16:15
In principle you'll find all you need to know in the TeXbook by Donald E. Knuth. The macro names with @ in them are not a special "notation" though but just a convention for writing "internal" macro or counter names. Normally @ is not a letter, so names with @ in them can not be used. In packages, this is allowed, or if it is explicitly turned on (as I did) with \makeatletter. \@ne is simply a predefined name denoting "1". – Stephan Lehmke Mar 26 '12 at 16:20

This works for arbitrarily long lists (at least two elements, of course):

\documentclass{article}
\usepackage{xparse}

\newcommand{\myMacro}[3]{[#1,#2,#3]} % define suitably

\ExplSyntaxOn
\NewDocumentCommand{\otherMacro}{mmm}{ \maps_splitargs:nnn {#1}{#2}{#3} }

\seq_new:N \l_maps_first_seq
\seq_new:N \l_maps_second_seq
\seq_new:N \l_maps_third_seq

\cs_new:Npn \maps_splitargs:nnn #1 #2 #3
{
\seq_set_split:Nnn \l_maps_first_seq  {,} { #1 }
\seq_set_split:Nnn \l_maps_second_seq {,} { #2 }
\seq_set_split:Nnn \l_maps_third_seq  {,} { #3 }
\prg_stepwise_inline:nnnn { 0 } { 1 } { \seq_length:N \l_maps_first_seq - 1 }
{
\tl_set:Nx \l_tmpa_tl
{
{ \seq_item:Nn \l_maps_first_seq { ##1 } }
{ \seq_item:Nn \l_maps_second_seq { ##1 } }
{ \seq_item:Nn \l_maps_third_seq { ##1 } }
}
\exp_after:wN \myMacro \l_tmpa_tl
\int_compare:nTF { ##1 = 0 }
{ \mapsto ( }
{ \int_compare:nTF { ##1 = \seq_length:N \l_maps_first_seq - 1 } { ) } { , } }
}
}
\ExplSyntaxOff

\begin{document}

$\otherMacro {a1,a2}{b1,b2}{c1,c2}$

$\otherMacro {a1,a2,a3}{b1,b2,b3}{c1,c2,c3}$

$\otherMacro {a1,a2,a3,a4}{b1,b2,b3,b4}{c1,c2,c3,c4}$

$\otherMacro {a1,a2,a3,a4,a5}{b1,b2,b3,b4,b5}{c1,c2,c3,c4,c5}$

\end{document}


## Important change

Due to the changes made to expl3 in Summer 2012, the code above should be replaced by the following:

\documentclass{article}
\usepackage{xparse}

\newcommand{\myMacro}[3]{[#1,#2,#3]} % define suitably

\ExplSyntaxOn
\NewDocumentCommand{\otherMacro}{mmm}{ \maps_splitargs:nnn {#1}{#2}{#3} }

\seq_new:N \l_maps_first_seq
\seq_new:N \l_maps_second_seq
\seq_new:N \l_maps_third_seq

\cs_new:Npn \maps_splitargs:nnn #1 #2 #3
{
\seq_set_split:Nnn \l_maps_first_seq  {,} { #1 }
\seq_set_split:Nnn \l_maps_second_seq {,} { #2 }
\seq_set_split:Nnn \l_maps_third_seq  {,} { #3 }
\int_step_inline:nnnn { 1 } { 1 } { \seq_count:N \l_maps_first_seq }
{
\tl_set:Nx \l_tmpa_tl
{
{ \seq_item:Nn \l_maps_first_seq { ##1 } }
{ \seq_item:Nn \l_maps_second_seq { ##1 } }
{ \seq_item:Nn \l_maps_third_seq { ##1 } }
}
\exp_after:wN \myMacro \l_tmpa_tl
\int_compare:nTF { ##1 = 1 }
{ \mapsto ( }
{ \int_compare:nTF { ##1 = \seq_count:N \l_maps_first_seq } { ) } { , } }
}
}
\ExplSyntaxOff

\begin{document}

$\otherMacro {a1,a2}{b1,b2}{c1,c2}$

$\otherMacro {a1,a2,a3}{b1,b2,b3}{c1,c2,c3}$

$\otherMacro {a1,a2,a3,a4}{b1,b2,b3,b4}{c1,c2,c3,c4}$

$\otherMacro {a1,a2,a3,a4,a5}{b1,b2,b3,b4,b5}{c1,c2,c3,c4,c5}$

\end{document}

-