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). 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 $\epsilon$-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 $\epsilon$-TeX-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 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 $\epsilon$-TeX \ifcsname and now tests for a command being undefined or \relax without the side effect of defining undefined commands to \relax.


Source: Is this command defined?

composition/macros/cette_commande_est_elle_definie.txt · Dernière modification: 2018/12/04 00:24 par jejust
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0