8

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.

2 Answers 2

5

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
    \advance\my@index\@ne
    \@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}
2
  • @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, 2012 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". Mar 26, 2012 at 16:20
4

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}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .