22

I am looking for a way in TeX to check if a macro was defined.

Currently I use a rather tangled way. I exploit a sort of side effect when comparing two macros via \ifx; this command returns:

  • true, if both macros are undefined,
  • false, if one macro only is defined.

Therefore, given a surely undefined macro \undefined and the macro \CheckMe, which may or may not be defined, I can use:

\ifx \CheckMe \undefined
  CheckMe is NOT defined
\else
  CheckMe is defined!
\fi

Is this correct? Can we define a macro ifdef? working like:

\ifdef CheckMe         %or \ifdef \CheckMe 
  CheckMe is defined!
\else
  CheckMe is NOT defined
\fi

I tried with something similar:

\def\ifnotdef#1{\ifx \csname#1\endcsname \undefined}

but it doesn't work.

5
  • 1
    Is e-TeX allowed?
    – egreg
    Jun 1, 2013 at 19:22
  • @egreg: Difficult to say. Actual problem is I have a large project. Sometime I prefer to compile single files. The idea is to define a \def\nostandalone\true in the main package; in the child files, to be sometimes be compiled alone, I would set on the top:` ` \ifx \nostandalone \undefined \documentclass{paper} \begin{document} \fi .... \ifx \nostandalone \undefined \documentclass{paper} \begin{document} \fi So it should be possible to load e-TeX before \documentclass{paper} with TeX methods.
    – antonio
    Jun 1, 2013 at 19:36
  • 3
    If you are using LaTeX, then e-TeX extensions are enabled by default, unless you're using a very old TeX distribution.
    – egreg
    Jun 1, 2013 at 19:39
  • @egreg: thanks, I didn't explore e-Tex possibilities.
    – antonio
    Jun 1, 2013 at 19:42
  • LaTeX defines a number of conditionals to check whether a macro is defined/not: \@ifdefinable, \@ifundefined Why not use them directly as part of your \ifdef?
    – Werner
    Jun 1, 2013 at 20:09

2 Answers 2

19

You can't define a macro \ifdef that can work with nested conditionals, because of the way TeX keeps track of \else and \fi. With a naive definition such as

\def\ifdef#1{\ifx#1\undefined}

one could surely say

\ifdef\CheckMe
  \string\CheckMe\space is not defined
\else
  \string\CheckMe\space is defined
\fi

but a construction such as

\ifnum\Acount=\Bcount
  something else
\else
  \ifdef\CheckMe
    \string\CheckMe\space is not defined
  \fi
\fi

will break if \Acount is equal to \Bcount, leaving a stray \fi: the \else will be matched to the first \fi, not to the second, because TeX doesn't expand tokens that are skipped in the true or false branch of a conditional; since \ifdef is a macro and not a conditional, the mismatch will bite you.

A workaround (tracing back to Knuth himself) is to define a macro in the following way:

\def\isundefined#1{TT\fi\ifx#1\undefined}

and call it as

\if\isundefined\CheckMe
  \string\CheckMe\space is not defined
\else
  \string\CheckMe\space is defined
\fi

This works also in nested conditionals because TeX will see the \if and match it with the correct \else or \fi. When expanded, \if TT\fi will do exactly nothing, leaving control to the following \ifx.


If e-TeX is allowed, there's an \ifdefined conditional that avoids choosing a macro name and trusting it will remain undefined:

\ifdefined\CheckMe
  \string\CheckMe\space is defined
\else
  \string\CheckMe\space is not defined
\fi

(notice the reversal of the conditions).

1
  • 2
    +1 \ifdefined is what I need!
    – antonio
    Jun 1, 2013 at 19:46
9

Changing slightly your definition, you will obtain Knuth's \ifundefined:

\def\ifundefined#1{\expandafter\ifx\csname#1\endcsname\relax}

It has some limitations, but seems to be that you need.

Here http://www.gust.org.pl/projects/pearls/2006p/index_html (Check if defined, no side effects by Bernd Raichle) you can find a deeper approach, with comments.

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .