I have learned at my own expense to be careful with scratch counters. However, I recently encountered a situation I cannot understand. Consider the following code
\documentclass{article}
% print the argument four times on numbered lines
\newcommand{\foo}[1]{1 #1\par 2 #1 \par 3 #1 \par 4 #1}
\makeatletter
% repeat "Bla" as many times as specified by the optional argument
\newcommand*{\baz}[1][1]{\count@=#1\@whilenum\count@>0\do{Bla\advance\count@\m@ne}}
\makeatother
\begin{document}
\foo{\baz[2]}
\end{document}
Instead of giving the desired output
1 BlaBla
2 BlaBla
3 BlaBla
4 BlaBla
the second and fourth line have only the number, but no "BlaBla".
I know at least two (possible) problems with the code given above.
1) A space or a \relax
should come after the counter assignment \count@=#1
, thus stopping TeX from expanding too far. (I know for sure of similar problems with \ifnum
.)
2) Scratch registers like \count@
may be dangerous and should be used preferably within a group.
The solution should thus be to replace the definition of \baz
by
\newcommand*{\baz}[1][1]{\begingroup\count@=#1\relax\@whilenum\count@>0\do{Bla\advance\count@\m@ne}\endgroup}
This actually gives the expected result. What, however, puzzles me is that both
\newcommand*{\baz}[1][1]{\begingroup\count@=#1\@whilenum\count@>0\do{Bla\advance\count@\m@ne}\endgroup}
(grouped but without \relax
) and
\newcommand*{\baz}[1][1]{\count@=#1\relax\@whilenum\count@>0\do{Bla\advance\count@\m@ne}}
(\relax
ed but not grouped) also work!
I'd appreciate any help to understand what is going on...
{1 {#1} \par 2 {#2} ...}
it will work without\relax
etc. I suppose that\count@
is used otherwise. For example,\newif
uses\count@
as well\count@=#1
and so tex is expanding the\@whilenum
while trying to get the number (as one can see I listened to @egreg talk ...).;-)