Macro - Repeat the pattern for any (even) number of arguments

If I would like to create a new command called \AddTwoArguments, which takes two arguments, I could do it as follows:

\newcommand{\AddTwoArguments}[2]{ {\bfseries#1} {#2'} }


So,

\AddTwoArguments{A}{B}


will output:

A ‘B’

Great. The world couldn't be happier.

But, imagine I would like to create a new command called \AddAnyEvenNumberOfArguments which works for any even number of arguments, which always follows the pattern above, for every pair of arguments.

For example,

\AddAnyEvenNumberOfArguments{A}{B}


would still give:

A ‘B’

whereas

\AddAnyEvenNumberOfArguments{A}{B}{C}{D}{E}{F}


would give:

A ‘B’ C ‘D’ E ‘F’

How could that be done please?

For example,

• What about an interface \AddAnyEvenNumberOfArguments{A}{B}{C}{D}{E}{F}\stop?
– Werner
Oct 6, 2017 at 2:33
• @Werner I am not familiar with your proposed command \stop, so I have difficulty understanding. Could you explain more or perhaps post an answer please? Oct 6, 2017 at 2:39
• Will the arguments of \AddAnyEvenNumberOfArguments always (a) consist of single letters and (b) be enclosed in curly braces? Separately, can it be guaranteed that there will always be an even number of arguments to the \AddAnyEvenNumberOfArguments directive? If not, i.e., if the number of arguments is odd, what is supposed to be done?
– Mico
Oct 6, 2017 at 3:05
• @Mico No, the arguments will not always consist of single letters. They are just used as dummies. Yes, they could always be enclosed in curly braces. Yes, it will be guaranteed that there are an even number of arguments. Oct 6, 2017 at 3:14

3 Answers

You can as a stopping criteria to halt the search for paired arguments. Such a stopping criteria could be \ByTwo ... \StopByTwo, say:

\documentclass{article}

\makeatletter
\newcommand{\ByTwo}{\@ifnextchar\StopByTwo\relax\@ByTwo}
\newcommand{\@ByTwo}[2]{ {\bfseries #1} {#2'} \ByTwo}
\makeatother
\let\StopByTwo\relax

\begin{document}

\ByTwo{A}{B}\StopByTwo

\ByTwo{A}{B}{C}{D}{E}{F}\StopByTwo

\ByTwo ABCDEF\StopByTwo

\end{document}

• +1. Instead of \let\StopByTwo\relax, one could also have \newcommand\StopByTwo{}. To the non-TeXperts, the second definition might make it (more) obvious that \StopByTwo doesn't "do" anything real except serve as the terminator key.
– Mico
Oct 6, 2017 at 3:45

Here is how to implement such a macro with using a stopper. The answer is in ConTeXt because I use the \dodoublegroupempty macro from ConTeXt. I am sure there will be a similar helper macro in the LaTeX kernel, which can be used in a LaTeX solution.

\unexpanded\def\ByTwo
{\dodoublegroupempty\doByTwo}

\def\doByTwo#1#2%
{\ifsecondargument
{\bf #1} ‘#2’
\expandafter\ByTwo
\fi}

\starttext
\startlines
\ByTwo{A}{B}
\ByTwo{A}{B}{C}{D}
\ByTwo{A}{B}{C}{D}{E}{F}
\stoplines
\stoptext


which gives

• Instead of using optional arguments you can check for a following argument with \doifnextbgroupelse, e.g. \define[2]\ByTwo{{\bf #1} ‘#2’ \doifnextbgroupcselse\ByTwo\relax}. Oct 6, 2017 at 10:16
• @Metafox: Thanks. Yes, that will be simpler. Oct 6, 2017 at 11:28

I propose an answer without end markup.

There is some problem with this question: what must be the answer if you provide an odd number of arguments? My answer to this question is that:

\AddAnyEvenNumberOfArguments{A}{B}{C}{D}{E}


should display

but you can easily change the code if you want another behavior.

\documentclass{article}

\makeatletter
\newcommand\AddAnyEvenNumberOfArgument{%
\@ifnextchar\bgroup{\AddCoupleArgument}{}
}
\newcommand\AddCoupleArgument[1]{%
\textbf{#1}
\@ifnextchar\bgroup{\AddSecondArgument}{\AddEmptySecondArgument}
}
\newcommand\AddSecondArgument[1]{%
#1'
\@ifnextchar\bgroup{\AddCoupleArgument}{}
}
\newcommand\AddEmptySecondArgument{%
'
}
\makeatother

\begin{document}
\AddAnyEvenNumberOfArgument{A}\par
\AddAnyEvenNumberOfArgument{A}{B}\par
\AddAnyEvenNumberOfArgument{A}{B}{C}\par
\AddAnyEvenNumberOfArgument{A}{B}{C}{D}\par
\AddAnyEvenNumberOfArgument{A}{B}{C}{D}{E}\par
\AddAnyEvenNumberOfArgument{A}{B}{C}{D}{E}{F}\par
\AddAnyEvenNumberOfArgument{A}{B}{C}{D}{E}{F}{G}
\end{document}


Pay attention that if the code after \AddAnyEvenNumberOfArguments begins with a left brace then this group will be eat by this macro! Logical. Normal. Add a \relax For exemple

\AddAnyEvenNumberOfArgument{A}{B}{C}{D}{E}{F}\relax
{\bfseries That's all folks}