7

Why can't I get what I want in the following code? MWE:

\documentclass{article}
\begin{document}
%
\def\aaa*{*}
\def\aaaAAA{AAA}
|\csname aaaAAA\endcsname|% typeset |AAA| as I desired.
|\csname aaa*\endcsname|% I want to get |*|, but get ||. So, what's wrong with my code?
%
\end{document}
  • 1
    \def\aaa*{*} does not define a macro called \aaa*. It defines a macro called \aaa that must always be followed by a *. |\csname aaa\endcsname*| would give you the output of \aaa*. To define \aaa* you need \expandafter\def\csname aaa*\endcsname{*}. – moewe Feb 1 at 8:17
6

That's because \csname aaa*\endcsname does not exist and therefore defaults to \relax which typesets nothing. Why does it not exist? Well, the problem is similar to No \makeatletter required?:

In \def\aaa*{*}, * does not form part of the definition, but instead forms part of the parameter text used. In order to define a macro to include a * in the definition name you'll have to use

\expandafter\def\csname aaa*\endcsname{*}% Similar to \@namedef{aaa*}{*}
9

Consider the following example

\def\aaa*{*}

\show\aaa*

Running TeX on it (any flavor), will report as follows on the console

> \aaa=macro:
*->*.
l.3 \show\aaa
             *
?

How do we read it? The primitive command \show reports the meaning of the following token; the to lines before the question mark tell us that \aaa* are two tokens, because * appears in the continuation line.

TeX is also telling us that \aaa is a macro that has a nonempty parameter text (what's reported before ->) consisting of an asterisk. In other words, \def\aaa*{*} instructs TeX that \aaa must be followed by * and the two tokens will be replaced by *.

For instance, you can call it also as

\aaa *

because the space after \aaa is ignored when building tokens from input.

If you want to use \csname, then it should be

\csname aaa\endcsname *

(the space before * is optional).

In case you're wondering how *-variants are implemented in LaTeX, here it is:

\newcommand{\foo}{\@ifstar\foostar\foonostar}
\newcommand{\foostar}{<what we want \foo* to do>}
\newcommand{\foonostar}{<what we want \foo to do>}

Possible arguments have to be grabbed by \foostar or \foonostar, depending on the desired syntax.

The approach with xparse is slightly different, but the command will not have the * as part of the name nonetheless.

  • Thank you so much for these detail explanations – lyl Feb 1 at 12:44

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.