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}
\usepackage{etoolbox}
\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{)}% note closeparen here (could be param)
\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}%
}
\makeatletter
\newcommand{\decl}[3]{%
% #1: decl id
% #2: decl symbol
% #3: # params
\csgdef{decl@#1}{#2}%
\global\expandafter\newcount\csname decl@#1@nparams\endcsname%
\csuse{decl@#1@nparams} #3\relax%
}
\newcommand{\usedecl}[1]{%
\newcount\c
\c \the\csuse{decl@#1@nparams}
\csuse{decl@#1}(\makecsv{\c}%
}
\makeatother
% declare some interface routines
\decl{foo}{FOO}{3}
\decl{bar}{BAR}{4}
\begin{document}
\usedecl{foo}{p1}{p2}{p3}\par
\usedecl{bar}{p1}{p2}{p3}{p4}\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?
Edit 1
It seems like my original MWE wasn't adequate to describe why someone might want this. I've updated the MWE with a use case. \decl
allows authors to declaratively define a C-style function, and \usedecl
allows the author to generate a use of the function, with its parameters bound to specific arguments.
This is similar enough to what I'm doing that it should help motivate the example.
etoolbox
orl3clist
.{foo}{bar}{foobar}
to{foo|bar|foobar}
. I do see how I could solve this problem somewhat generically with a list though, with a generic\makelistfromargs{\listname}{\counter}
that reads a bunch of arguments into an internal list. Is this the more common solution that you see people doing?\makecsv{\c}{abc}{def}{ghi}
?