Ceci est une ancienne révision du document !
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>\undefined
<stuff> …
(which of course actually tests that the command doesn't
exist). 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. 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:
\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.
So, in an -based system, the following two conditional clauses do
the same thing:
\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 original
\@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 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
.
Source: μfaquk>FAQ-isdef&Is this command defined?¢
metatag-keywords=(LaTeX,programmation LaTeX,tester si une macro est définie,savoir si une commande est définie)