I wish to create two macros: one that takes a known number, and another that takes an unknown number of arguments that are comma-separated and does something with them. There have been a few answers to this question before see (here and here), but they always use modern LaTeX packages such as xparse
. For example, I could create a new fraction command (known number of args) by doing
\ExplSyntaxOn
\makeatletter
\def\numargs{2}
\NewDocumentCommand{\frc}{>{\SplitArgument{\numargs-1}{,}}m}{\@frc@#1}
\NewDocumentCommand{\@frc@}{mm}{\frac{#1}{#2}}
\makeatother
\ExplSyntaxOff
and using it with \frc{1,2}
, effectively doing the same as \frac{1}{2}
. Another example would be to create a bolded list (unknown number of args) with
\ExplSyntaxOn
\NewDocumentCommand{\bflist}{m}{\clist_map_inline:nn{#1}{\@bflist@{##1}}}
\newcommand{\@bflist@}[1]{\bf #1}
\ExplSyntaxOff
and using it with \bflist{a, b, c, d, e, f}
, etc, which would create the bolded list a b c d e f. Both of these solutions use modern LaTeX tools; I am wondering, is there a way to create these commands in plain TeX? Or at the very least, in LaTeX without using external packages?
Best Answer
The solution in very simple in Plain TeX (or more precisely: using only TeX primitive commands)
Note that
\boldlistA
uses first unseparated parameter#1
followed by second separated#2
in order to remove spaces after commas. We need not to do it in the\frc
macro because it is intended for math mode where spaces are ignored by TeX.Second example in more detail: Assume syntax:
\boldlist{a,b,cxy,d}
without spaces after commas. Then we can define:This is recursive call of
\boldlistA
. The parameter#1
isa
in first call (because it is separated by comma), then it isb
, thencxy
, thend
and finally, it is\end
. The test\ifx\end#1
stops this recursion.If you want to use optional spaces before parameters (after comma) but you want to ignore them, i.e.
\boldlist{a, b, cxy,d}
then the\boldlistA
have#1
unseparated: the#1
is first non-space token, spaces are ignored by TeX. The#2
is separated by comma. It is empty in the first case:#1=a
,#2=empty
, it is empty in second case#1=b
, space before it is ignored,#2=empty
, but it is not empty in third case:#1=c
, space before it is ignored,#2=xy
.