[Tex/LaTex] Is a TeX macro defined

conditionalsmacrostex-core

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.

Best Answer

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).

Related Question