I'd attack this from a different point of view. Primitive conditionals in TeX test for a condition, which can absorb tokens from the input stream or not until the truth or falsehood of the condition can be established. So, let's denote by
<IF> the primitive conditional together with the (possibly empty) list of tokens that must be absorbed. For instance \ifhmode needs no token, \ifx needs two. In some cases (\if, \ifcat, \ifnum, \ifdim) TeX perform expansions in order to find the required kind of tokens for the test; in others (\ifx, \ifmmode, \ifhmode, \ifvmode \ifinner, \iftrue, \iffalse) no expansion is performed. Thus <IF> will denote the conditional and the required tokens after expansion has taken place and the condition can be tested.
The typical construction you're referring to is
<IF>
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
where we already have
\long\def\@firstoftwo#1#2{#1}
\long\def\@secondoftwo#1#2{#2}
More generally, we have
<IF><true>\else<false>\fi
or
\IF<true>\fi
where both <true> and <false> can be empty.
The condition is true
TeX will simply remove <IF> from the input stream, leaving either
<true>\else<false>\fi
or
<true>\fi
The condition is false
TeX looks for the next \else token, taking into account nested conditionals that might appear in <true> without expanding anything. So an \else belonging to a nested \if...\else\fi inside <true> will be skipped. The expansion is empty also in this case and every token up to \else will disappear. In case no matching \else is found, TeX will stop looking at the matching \fi that should better be somewhere. So, in the two cases, we'd get either
<false>\fi
or just nothing if no \else branch was there.
This is proved by the following TeX input:
\def\showx{\show\x}
\def\showif{\afterassignment\showx
\expandafter\def\expandafter\x\expandafter}
\showif{\ifvmode<true>\else<false>\fi}
\showif{\ifvmode<true>\fi}
\showif{\ifhmode<true>\else<false>\fi}
\showif{\ifhmode<true>\fi}
\bye
Running TeX on it will produce the following transcript:
This is TeX, Version 3.1415926 (TeX Live 2012)
(./plkfi.tex
> \x=macro:
-><true>\else <false>\fi .
\showx ->\show \x
l.5 \showif{\ifvmode<true>\else<false>\fi}
?
> \x=macro:
-><true>\fi .
\showx ->\show \x
l.6 \showif{\ifvmode<true>\fi}
?
> \x=macro:
-><false>\fi .
\showx ->\show \x
l.7 \showif{\ifhmode<true>\else<false>\fi}
?
> \x=macro:
->.
\showx ->\show \x
l.8 \showif{\ifhmode<true>\fi}
?
What happens next
The expansion of \else consists in removing everything up to the matching \fi and leaving nothing in the input stream. Nested conditionals will be taken into account as before.
The expansion of \fi is empty.
The role of \expandafter
Now we have the bases upon which we can drop \expandafter.
Let's see a typical usage:
\def\@ifundefined#1{%
\expandafter\ifx\csname#1\endcsname\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
What we want is to be able to say
\@ifundefined{foo}{T}{F}
So the macro built with the argument as name is compared to \relax (this is really the uninteresting part) and then the true or false branch is followed.
After the removal of the <IF> we remain with
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi{T}{F}
and now TeX duly expands the first token. This triggers the expansion of \else and here's where the fun begins.
The expansion of \expandafter consists in expanding (if possible) the token after the next one and vanishing. Thus \else is expanded according to the rule above and we are left with
\@firstoftwo{T}{F}
that results in leaving T in the input stream.
Suppose now that the condition is false. Then the <IF> is removed together with everything up to \else, leaving
\expandafter\@secondoftwo\fi{T}{F}
Now \expandafter does its job of expanding \fi and vanishing. Thus we get
\@secondoftwo{T}{F}
that finally leaves F.
Important note
In the case of \@ifundefined{foo}{T}{F} we are able to get at T or F without ever executing a command: just macro expansion has been used. This makes \@ifundefined and similarly defined macro usable inside \edef:
\edef\test{\@ifundefined{foo}{T}{F}}
will be equivalent to
\def\test{T}
in case \foo is defined (and not equivalent to \relax, as usual in LaTeX) or to
\def\test{F}
if \foo is undefined (or equivalent to \relax).
What would happen without \expandafter? With a true conditional TeX would be confronted with
\@firstoftwo\else\@secondoftwo\fi{T}{F}
and the two arguments to \@firstoftwo would be \else and \@secondoftwo, which wouldn't do anything useful, would they?
Similarly, for a false condition we'd get
\@secondoftwo\fi{T}{F}
and again things would go wrong.
\expandafters are important but nobody says why ... – PLK Apr 09 '13 at 15:53\ifxand\ifnumand not a general thing about dealing with 3+4 args with\*oftwo? – PLK Apr 09 '13 at 16:07\let\next=...idiom). Alan Jeffrey popularised it and introduced it to the LaTeX sources for latex2e, although I seem to recall he denied inventing it and had picked it up from somewhere.... – David Carlisle Apr 09 '13 at 16:09\if..and not\@firstof..compare latex2.09\def\@iwhiledim#1{\ifdim #1\let\@nextwhile\@iwhiledim\else\let\@nextwhile\@whilenoop\fi\@nextwhile{#1}}with latex2e\long\def\@iwhiledim#1{\ifdim #1\expandafter\@iwhiledim\else\expandafter\@gobble\fi{#1}}– David Carlisle Apr 09 '13 at 16:14