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,

  • What about an interface \AddAnyEvenNumberOfArguments{A}{B}{C}{D}{E}{F}\stop? – Werner Oct 6 '17 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? – Vincent Mia Edie Verheyen Oct 6 '17 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 '17 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. – Vincent Mia Edie Verheyen Oct 6 '17 at 3:14
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. 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 '17 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

  • 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}. – Wolfgang Schuster Oct 6 '17 at 10:16
  • @Metafox: Thanks. Yes, that will be simpler. – Aditya Oct 6 '17 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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.