\if
compares the following two tokens after macro expansion, because it wants to compare unexpandable tokens.
Thus \if\first\second...\fi
expands \first
and the input stream has now
\if abc\second...\fi
and the comparison between a
and b
returns false.
You can make \first
and \second
unexpandable by saying
\if\noexpand\first\noexpand\second...\fi
but this would return true independently of the meaning of \first
and \second
, because \if
compares character codes and, if a token is not a character, it is considered as having character code 256 (not really, but it is convenient to think so). A control sequence will be considered as having character code 256 unless it has been defined with
\let\cs=a
(or any other character) and in this case \if a\cs
would return true.
Of course, the value 256 represents any number that cannot be a character code, so it would be 0x11000
for XeLaTeX or LuaLaTeX, where character codes can be as high as 0x10FFFF
.
Usage of \if
is not easy, and has many subtleties. For instance one cannot use directly an active character for comparison and it must be preceded (after macro expansion) by \noexpand
.
A clever example of \if
is for testing whether an argument is empty:
\def\cs#1{%
\if\relax\detokenize{#1}\relax
The argument is empty%
\else
The argument #1 is non empty%
\fi
}
It uses \detokenize
which is an e-TeX feature. If the argument is empty, the comparison would be between \relax
and \relax
, which are equal as far as \if
is concerned; otherwise, \detokenize
would return a string of characters (of category code 12) and \relax
is never equal to a character for \if
. So with
\cs{abc}
one would get
\if\relax abc\relax
The argument is empty%
\else
The argument #1 is non empty%
\fi
and the true text would be
bc\relax The argument is empty\else
which would be discarded.
Similarly, with
\if a\first true\else false\fi
the expansion of \first
gives
\if aabctrue\else false\fi
and, since the first two unexpandable tokens after \if
are equal, the true text is
bctrue
while \else false\fi
will be discarded.