summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/generic/FAQ-en/html/FAQ-isdef.html
blob: ae9732462f955a81d7f91221d7c1463fda7f633e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<head>
<title>UK TeX FAQ -- question label isdef</title>
</head><body>
<h3>Is this command defined?</h3>
<p/>Macro sets from the earliest days of TeX programming may be
observed to test whether commands exist by using
<blockquote>
<code>\</code><code>ifx</code> csx<code><em>command</em></code> <code>\</code><code>undefined</code> &lt;<i>stuff</i>&gt; &hellip;
</blockquote><p>
(which of course actually tests that the command <em>doesn&rsquo;t</em>
exist).  LaTeX programmers can make use of the internal command
<blockquote>
  <code>\</code><code>@ifundefined{</code><em>cmd name</em><code>}{</code><em>action1</em><code>}{</code><em>action2</em><code>}</code>
</blockquote><p>
which executes <code>action1</code> if the command is undefined, and
<code>action2</code> if it is defined
(<em>cmd name</em> is the command name only, omitting the &lsquo;<code>\</code>&rsquo; character).
<p/>The <code>\</code><code>@ifundefined</code> command is based on the sequence
<blockquote>

<pre>
\expandafter \ifx \csname cmd name\endcsname \relax
</pre>
</blockquote><p>
which relies on the way <code>\</code><code>csname</code> works: if the command doesn&rsquo;t
exist, it simply creates it as an alias for <code>\</code><code>relax</code>.
<p/>So: what is wrong with these techniques?
<p/>Using <code>\</code><code>undefined</code> blithely assumes that the command is indeed not
defined.  This isn&rsquo;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 <code>\</code><code>@undefined</code>, adding a single
level of obscurity.
<p/>The <code>\</code><code>@ifundefined</code> 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 &ldquo;<code>\</code><code>relax</code>&rdquo;
names serve no purpose whatever.  Even so (sadly) there are places in
the code of LaTeX where the existence of the <code>\</code><code>relax</code> is relied
upon, after the test, so we can&rsquo;t get away from <code>\</code><code>@ifundefined</code>
altogether.
<p/>David Kastrup offers the (rather tricky)
<blockquote>
<pre>
{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ...
</pre>

</blockquote><p>
which &ldquo;creates&rdquo; the <code>\</code><code>relax</code>-command inside the group of the first
<code>\</code><code>expandafter</code>, therefore forgets it again once the test is done.
The test is about as good as you can do with macros.
<p/>The <a href="FAQ-etex.html">e-TeX system</a> system comes to our help here: it
defines two new primitives:
<ul>
<li> <code>\</code><code>ifdefined</code>, which tests whether a thing is defined (the
  negative of comparing with <code>\</code><code>undefined</code>, as it were), and
<li> <code>\</code><code>ifcsname</code> <code>cmd name</code><code>\</code><code>endcsname</code>, which does the
  negative of <code>\</code><code>@ifundefined</code> without the <code>\</code><code>relax</code>-command
  side-effect.
</ul>
So, in an e-TeX-based system, the following two conditional clauses do
the same thing:
<blockquote>
<pre>
\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
</pre>
</blockquote><p>
However, after using the LaTeX
<code>\</code><code>@ifundefined{foo}</code>&hellip;, the conditionals will detect the
command as &ldquo;existing&rdquo; (since it has been <code>\</code><code>let</code> to <code>\</code><code>relax</code>);
so it is important not to mix mechanisms for detecting the state of a
command.
<p/>Since most distributions nowadays use e-TeX as their base executable
for most packages, these two primitives may be expected appear widely
in new macro packages.
<p/><p/><p/><p>This question on the Web: <a href="http://www.tex.ac.uk/cgi-bin/texfaq2html?label=isdef">http://www.tex.ac.uk/cgi-bin/texfaq2html?label=isdef</a>
</body>