7

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,

4
  • 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?
    – O0123
    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.
    – O0123
    Oct 6, 2017 at 3:14

3 Answers 3

7

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

enter image description here

\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
  • +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
4

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

enter image description here

2
  • 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.
    – Aditya
    Oct 6, 2017 at 11:28
2

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}

You must log in to answer this question.

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