Frequently Asked Question List for TeX


Is this command defined?

Macro sets from the earliest days of TeX programming may be observed to test whether commands exist by using \ifx\<command>\undefinedstuff› … (which of course actually tests that the command doesn’t exist). LaTeX programmers can make use of the internal command \@ifundefined{cmd name}{action1}{action2} which executes action1 if the command is undefined, and action2 if it is defined (cmd name is the command name only, omitting the \ character).

The \@ifundefined command is based on the sequence

\expandafter \ifx \csname cmd name\endcsname \relax

which relies on the way \csname works: if the command doesn’t exist, it simply creates it as an alias for \relax.

So: what is wrong with these techniques?

Using \undefined blithely assumes that the command is indeed not defined. This isn’t entirely safe; one could make the name more improbable, but that may simply make it more difficult to spot a problem when things go wrong. LaTeX programmers who use the technique will typically employ \@undefined, adding a single level of obscurity.

The original \@ifundefined mechanism had the unfortunate property of polluting the name space: each test that turns out undefined adds a name to the set TeX is holding, and often all those \relax names serve no purpose whatever.

David Kastrup offers the (rather tricky)

{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ...

which “creates” the \relax-command inside the group of the first \expandafter, therefore forgets it again once the test is done. The test is about as good as you can do with macros.

The ε-TeX system system comes to our help here: it defines two new primitives:

So, in an ε-TeX-based system, the following two conditional clauses do the same thing:

  \message{\string\foo\space is defined}%
  \message{no command \string\foo}%
\ifcsname foo\endcsname
  \message{\string\foo\space is defined}%
  \message{no command \string\foo}%

However, after using the original LaTeX \@ifundefined{foo}…, the conditionals will detect the command as “existing” (since it has been \let to \relax); so it is important not to mix mechanisms for detecting the state of a command.

In the 2018 LaTeX release, the definition of \@ifundefined was adapted to use the ε-TeX \ifcsname and now tests for a command being undefined or \relax without the side effect of defining undefined commands to \relax.

FAQ ID: Q-isdef
Tags: macros