5

I define a command \test that does nothing but define a control sequence \c[count], where [count] is the current text value of the counter count at the time \test is executed. I want \c[count] to output the text "Number \thecount", where \thecount should be the value of count at time of execution.

\documentclass[12pt]{article}

\newcounter{count}

\newcommand{\test}{\expandafter\def\csname c\thecount\endcsname{Number \thecount~}}

\begin{document}

\setcounter{count}{1}
\test 
\setcounter{count}{2}
\test
\setcounter{count}{3}
\test

\csname c1\endcsname
\csname c2\endcsname
\csname c3\endcsname

\end{document}

This outputs: "Number 3 Number 3 Number 3". I believe this means that \thecount in the output of \test was not expanded during each \test.

How can I fix this to display "Number 1 Number 2 Number 3" as intended? I'm unsure how to use \expandafter for this, my attempts keep breaking everything. I relatively new to this sort of LaTeX, so I'd appreciate any help on this matter.

  • 3
    Replace the \def by \edef. You want the \thecount to be expanded at the time it's defined, otherwise \thecount will take the value of the counter at the time it's used – Phelype Oleinik Sep 14 at 15:08
  • @PhelypeOleinik Thank you! – greenturtle3141 Sep 14 at 15:12
6

Let's see what happens.

  1. The replacement text of a macro is absorbed with no interpretation or macro expansion during \def, except for the fact that explicit braces must be balanced, which is necessary for determining where the replacement text ends.

  2. When \csname is being expanded, tokens are fully expanded until only unexpandable tokens remain, up to the matching \endcsname.

So, if you do \def\foo{Number \thecount}, the replacement text will contain \thecount which will be expanded after the expansion of \foo upon usage. What's the macro name is completely irrelevant.

To the contrary, if the value of count is 1, \expandafter\def\csname foo\thecount\endcsname{whatever} will define the macro with name “foo1” (that cannot be accessed unless using \csname or changing the category code of 1).

Note that a single expansion step on \thecount will not produce 1, but just

\@arabic\c@count

because LaTeX by default will do \def\thecount{\@arabic\c@count}, so a single \expandafter would not be sufficient: three expansion steps are necessary, because \@arabic is defined as

> \@arabic=macro:
#1->\number #1.

and so another step is necessary to get the value in Arabic numerals.

However, \@arabic is fully expandable, so you can use \edef:

\newcommand{\test}{\expandafter\edef\csname c\thecount\endcsname{Number \thecount~}}

because \edef is the same as \def, but the replacement text consists of the full expansion of the <balanced text> in the body of the definition.

Also

\newcommand{\test}{%
  \expandafter\def\csname c\thecount\expandafter\endcsname\expandafter{%
    \expanded{Number \thecount~}%
  }%
}

would work, because the trailing \expandafter in \csname is expanded, triggering the expansion of \expandafter before {, which triggers the expansion of \expanded. Of course \edef is much simpler, but \expanded can be useful in other cases.

Be careful with \edef or \expanded, because “dangerous” tokens might need \noexpand.

  • Thank you! This was very informative. – greenturtle3141 Sep 15 at 0:01

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.