Friday, 7 June 2013

Commands that may take a variable number of arguments

Commands that may take a variable number of arguments

I have a situation where I want to define a command that takes a variable number of arguments, where the number of arguments is known programmatically via a \count, and process the parameters in some way (say as if they are a list).
As an example, say I'd like to output the parameters as a comma-separated list.
\newcommand{\makecsv}[N]{#1, #2, ..., #N}
The code that I've come up with to do this kind of operation (in a generic-ish way) essentially takes a command, \csv and expands it recursively N times. \csv needs to know how to continue the recursion, and has some state that I'd like to thread through the recursion (rather than using \global).
\documentclass{report}

\makeatletter
\newcommand{\ifzero}[3]{%
  % #1: count
  % #2: state for #3
  % #3: macro to expand to
  %     - should take at least 2 parameters
  %     - ##1: count threaded through
  %     - ##2: macro state threaded through
  \ifnum\c > 0
    \def\tmp@f##1##2##3{##1{##2}{##3}}%
    \advance#1 -1%
  \else
    \def\tmp@f##1##2##3{}%
  \fi
  \tmp@f{#3}{#1}{#2}%
}
\makeatother

\newcommand{\csv}[3]{
  % #1: count
  % #2: separator state
  % #3: string to concat
  %
  #2#3\ifzero{#1}{, }{\csv}%
}

\newcommand{\makecsv}[1]{%
  \ifzero{#1}{}{\csv}%
}

\begin{document}
\newcount\c
\c 3
\makecsv{\c}{foo}{bar}{foobar}\par
\c 4
\makecsv{\c}{foo}{bar}{foobar}{baz}\par
\end{document}
Is this a reasonable thing to do in 2e, or is there some sort of standard approach to this that is normally used?

No comments:

Post a Comment