8

Context

Consider the following situation.

\documentclass{minimal}
\makeatletter
\expandafter\def\csname/test\endcsname{%
  \foo{bar}}
\def\mymacro#1{%
  % Note the / *after* #1
  \expandafter\expandafter\expandafter\mymacro@i\csname/#1/\endcsname}
\def\mymacro@i\foo#1{%
  \def\temp{#1}%
  \show\temp}
\mymacro{test}
% Error: Use of \mymacro@i doesn't match its definition.
\begin{document}
\end{document}

I made a typo in the definition of \mymacro adding a / before \endcsname. The error shown made me believe that /test was improperly expanded by the three \expandafter but I was wrong. As /test/ is not defined, it silently expands to \relax and yes TeX is right saying that Use of \mymacro@i doesn't match its definition since I feed it with a \relax instead of a \foo.

Question

This behavior of \csname defined control sequence (that is expanding to \relax when undefined) is really handy but sometimes I'd like to deactivate it and maybe issue an Undefined control sequence error. Is it possible?

10

You cannot alter the behaviour of \csname, but you can use e-TeX's \ifcsname to issue an error:

\csname
  \ifcsname#1\endcsname
  \else
    \expandafter\UndefinedName
  \fi
  #1%
\endcsname

where \UndefinedName is deliberately not defined. TeX will then issue an error complaining about Undefined control sequence, followed by #1 (which is what you actually want to complain about).

(Unlike \@ifundefined, \ifcsname is expandable and does not add to the hash table.)

1
  • Thanks Joseph. That fits exactly my needs since i need it in an expandable context. – cjorssen Jan 27 '12 at 13:25
2

You can check the command for existence and invoke the error yourself.

\@ifundefined{/#1/}{%
  \GenericError{}{%
    Command /#1/ undefined!
  }{%
    See the definition of \protect\mymacro!
  }
}{}%

The \@ifundefined macro uses \csname so it will define the macro as \relax. I don't think that this is an issue (we invoke the error anyways), but you can surround the code by \begingroup ... \endgroup to make the definition local.

3
  • LaTeX2e's \@ifundefined will leave the macro equal to \relax unless you use grouping, if it was previously undefined. – Joseph Wright Jan 27 '12 at 9:21
  • @JosephWright I know, but I don't think it is that an issue as we invoke the error message. However, I should have mentioned it, thanks! – yo' Jan 27 '12 at 9:36
  • Thanks. However I prefer Joseph's solution since it is expandable. – cjorssen Jan 27 '12 at 13:27
1

In the question it is written:

This behavior of \csname defined control sequence (that is expanding to \relax when undefined) is really handy but sometimes I'd like to deactivate it and maybe issue an Undefined control sequence error. Is it possible?

\csname is used for obtaining a control sequence token from a sequence of tokens that at some stage of expansion yield a sequence of character tokens representing the name of the control sequence token in question. In case the control sequence token in question was undefined when applying \csname, it will get assigned the meaning of the \relax-primitive. (That assignment is restricted to the current scope even if the \globaldefs-parameter has a positive value.)

Thus in this case, the \csname-defined control sequence does not get expanded to \relax. It does not get expanded at all as it is not expandable as it has the same meaning as the \relax-primitive which is not an expandable token.

"Hitting" unexpandable tokens with \expandafter does not affect these tokens. \expandafter itself is expandable. All expansion takes place in TeX' mouth. Therefore processing \expandafter will take place in TeX' mouth. Unexpandable tokens are not affected by that. They reach the stomach of TeX.

\mymacro@i is expected to be delimited by the control word token \foo while the first \expandafter-chain from the expansion of \mymacro{test} "hits" \csname which in turn delivers the unexpandable control word token \/test/ whose meaning equals the meaning of the unexpandable \relax-primitive. That unexpandable control word token is not affected when being "hit" by the second \expandafter-chain.

By the way 1: With delimited arguments usually the argument delimiting tokens get removed when TeX is gathering the arguments. Therefore in relation to gathering arguments, the meanings of argument delimiting tokens don't matter. You can even happily use tokens that are undefined as argument delimiters.

By the way 2: Don't use the minimal class for minimal examples. Use the article class instead.
The minimal class was written by the developers of the LaTeX2e-package for testing the class loading mechanism of the LaTeX2e-package.

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.