[comp.text.tex] Testing for empty arguments explanation & solution

marcel@cs.caltech.edu (Marcel van der Goot) (05/03/91)

debi erpenbeck (dje@lanl.gov) asked how to test whether an argument is
empty:
> \ifx#1=\empty
> \if#1=\empty
> \ifcat#1=\empty

This is a good instance of the problem Raymond Chen
(raymond@math.berkeley.edu) mentioned in a different posting
[Re: Is there a Tex short-reference handbook (not Knuth)?]:

	I've found that many of the TeX misunderstandings are not problems
	with primitives and macros, but rather with the more fundamental way
	TeX scans and expands tokens.

Here's what goes wrong with your attempted solutions:
1. If you look it up (ch. 20), you'll see that \if, \ifcat, and \ifx
   all should be followed by two tokens, without `=' sign in between.
   (\ifnum and \ifdim use an `=' sign).
2. Take for instance \ifx#1=\empty. Now suppose #1 is indeed empty. When
   TeX comes across `#1' it substitutes the argument; therefore, in this
   case it substitutes nothing at all. In other words, if #1 is empty, the
   test is equivalent to \ifx=\empty, which compares an equals sign with
   the macro \empty. (If the equals sign is omitted, you would be comparing
   the macro \empty with whatever token follows it.)
3. Take \ifx#1=\empty again. Suppose #1 is an equals sign. In that case \ifx
   is followed by two equal signs, which means that the test is true. If
   you omit the equals sign, the test would be true if #1 was the macro
   \empty, rather than just empty. (The test can also be true if #1 consists
   of more than one token.)
Anyway, what you should remember about all this is that \if etc. compare
tokens, and that `#1' is not a token: it's value (which consists of tokens)
is substsituted.

Here are two methods that work:
With \ifx:

\def\firstmacro#1%
   {\def\tmp{#1}%
    \ifx\tmp\empty
	 \message{Arg1 is empty}%
    \else\message{Arg1 is not empty}%
    \fi
   }

With \if:

\def\secondmacro#1%
   {\if.#1.% you can use another character instead of `.'
	 \message{Arg1 is empty}%
    \else\message{Arg1 is not empty}%
    \fi
   }

The second solution will only work if #1 cannot possibly start with
a dot. Also, the behavior with respect to expansion of #1 is different:
	\firstmacro{}		--> empty
        \firstmacro{\empty}	--> not empty
	\secondmacro{}		--> empty
	\secondmacro{\empty}	--> empty
If you replace \def\tmp in \firstmacro by \edef\tmp:
	\firstmacro{\empty}	--> empty


                                          Marcel van der Goot
 .----------------------------------------------------------------
 | Blauw de viooltjes,                    marcel@vlsi.cs.caltech.edu
 |    Rood zijn de rozen;
 | Een rijm kan gezet
 |    Met plaksel en dozen.
 |