\
ifx
csxcommand
\
undefined
<stuff> ...
(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).
\
@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
.
\
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 \
@ifundefined
mechanism has 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. Even so (sadly) there are places in
the code of LaTeX where the existence of the \
relax
is relied
upon, after the test, so we can’t get away from \
@ifundefined
altogether.
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.
\
ifdefined
, which tests whether a thing is defined (the
negative of comparing with \
undefined
, as it were), and
\
ifcsname
cmd name
\
endcsname
, which does the
negative of \
@ifundefined
without the \
relax
-command
side-effect.
\ifdefined\foo \message{\string\foo\space is defined}% \else \message{no command \string\foo}% \fi % \ifcsname foo\endcsname \message{\string\foo\space is defined}% \else \message{no command \string\foo}% \fi
However, after using the 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.
This question on the Web: http://www.tex.ac.uk/cgi-bin/texfaq2html?label=isdef