Testing for LaTeX and TeX macro definitions

Keywords: latex text conditional macro ifx

When modifying a LaTeX environment it is often desirable to add new (optional) macro variables which evoke different effects to the document dependent on whether or not they are defined with a non-empty value.

As an example, consider the case where we wish to modify the standard Title Page routines to include a listing for spokesmen and collaboration members in place of the standard author field.

The desired result would be something that looked like:

Paper Title


Spokesmen
John Smith

Collaborators
Susi Que, Alen Smithee

But in the advent that the writer did not use one or both of the fields, you would want to exclude not only the names, but the "Spokesmen" or "Collaborators" text.

The way to accomplish this is by testing for the existence of a non-empty macro definition, and then branching on the result of the test. In TeX and LaTeX there is no automatic way to perform this test.

\if Constructs

The standard "\if" command does not test for a binary result, rather it always performs a character comparison on two arguments after macro expansion. As a result the following \if construct will work (sometimes):

\if \@testmacro \@relax \@relax
Commands to use if the macro is undefined
\else
Commands to use if the macro IS defined
\fi

The difficulty with this construct is that will fail if \@testmacro has certain special characters in it (mainly the comment character '%') or some type of unusual expansion for which the first two characters match. It also suffers from a condition where characters left over after the comparison can actually fall into the true branch of the statement and be executed as commands. All in all while this approach can be use, it is prone to difficulties.

\ifx Constructs

Given the problems associated with the intuitive use of \if there is a better method of testing for macro existence using the little known (yet standard) TeX \ifx directive. This directive compares two arguments, but does NOT expand macros. This has the effect of causing a match on two macros only when:

  • Both arguments are macros AND their first level expansion is identical AND they have the same status with respect to \long and \outer

  • One consequence of this statement is that two undefined macros will cause a match. Hence the following construct will ALWAYS correctly test whether a given macro is or is not defined:


    \ifx \@testmacro \@empty
    Code to be executed if the macro is undefined
    \else
    Code to be executed if the macro IS defined
    \fi

    So as an example, we will consider our idea of a \spokesman command. So in a user defined style file (loaded with the \usepackage{nameofpackage}) we would put the following:


    %
    % Define a spokesmen variable and initialize it
    \newcommand{\spokesmen}[1]{\def\@spokesmen{#1}}
    \spokesmen{}
    %
    % Properly clear the global variables and commands
    % (is is more a convention to prevent confusion with
    % symbols defined at other scopes)
    \global\let\@spokesmen\@empty
    \global\let\spokesmen\relax

    % % % Some where within the style file where we redefine
    % the command or environment we wish to modify
    \renewcommand{\maketitle}{%
    \begin{titlepage}
    .
    .
    .
    %
    % Print the word Spokesmen
    % and the name of the person only if the
    % writer has defined it
    \ifx\@spokesmen\@empty
    \relax
    \else
    \begin{tabular}[t]{c}
    \em{Spokesmen:}\\
    \@spokesmen
    \end{tabular}\par%
    \fi%
    .
    .
    .

    If you have further questions consult:
    TeX for the Impatient, Paul W. Abrahams -- ISBN 0-201-51375-7
    For a detailed listing of all the standard TeX commands.
    Andrew J. Norman
    Last modified: Mon Dec 18 10:32:45 EST 2000