32

I see a lot of macros which are conditional tests followed by a {true}{false} pair defined so that they result in either:

\expandafter\@firstoftwo

or

\expandafter\@secondoftwo

Why are these \expandafters there? I would have though they'd just catch the first brace in the following {true}{false} pair?

8
  • 2
    This is basically asking for the answers to this question
    – Ryan Reich
    Commented Apr 9, 2013 at 15:47
  • When I read that question, everyone agrees the \expandafters are important but nobody says why ...
    – PLK
    Commented Apr 9, 2013 at 15:53
  • If you read Martin Scharrer's answer he alludes to it, but does sort of assume you know what he's looking at. I will contribute an answer, but I still think it's a duplicate.
    – Ryan Reich
    Commented Apr 9, 2013 at 15:56
  • 4
    It's probably worth noting that this idiom doesn't appear in plain tex or latex2.09 (which used a \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.... Commented Apr 9, 2013 at 16:09
  • 1
    @PLK it is all to do with \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}} Commented Apr 9, 2013 at 16:14

3 Answers 3

44

The \expandafters are to deal with the following \else or \fi. As in the question that Ryan links to, the full code is something like:

\def\ifeq#1#2{%
 \ifx#1#2\relax
   \expandafter\@firstoftwo
 \else
   \expandafter\@secondoftwo
 \fi
}

Let's trace what happens. We put \ifeq\stuff\nonsense{true}{false} into our document. The \ifeq absorbs the \stuff and \nonsense so we have after the first expansion:

\ifx\stuff\nonsense\relax
  \expandafter\@firstofone
\else
  \expandafter\@secondoftwo
\fi
{true}{false}

Let's suppose that \stuff is \nonsense (that is, that the conditional is true). Then the \ifx starts expanding everything in its "true" path, which is defined as everything up to the next \else or \fi (modulo nesting). The key point is that it starts expanding first and doesn't look ahead to find the \else or \fi. TeX figures it'll know it when it gets to it. So we have:

  \expandafter\@firstoftwo
\else
  \expandafter\@secondoftwo
\fi
{true}{false}

TeX now expands that \expandafter. This has the effect of reaching over the \@firstoftwo to the \else and expanding that. "Expanding" the \else means removing it and everything up to the matching \fi from the stream. So we are left with:

\@firstoftwo{true}{false}

And then this gets expanded to the simple true.

Without the \expandafters there, we get to:

  \@firstoftwo
\else
  \@secondoftwo
\fi
{true}{false}

TeX is still expanding the true branch so expands \@firstoftwo. This absorbs two tokens/braced groups from the stream. These happen to be \else and \@secondoftwo. It then leaves the first in the stream so we get

\else
\fi
{true}{false}

The \else matches the conditional so TeX absorbs this and everything up to the \fi leaving {true}{false} in the stream. Which isn't what we wanted.

In summary, the \expandafters are to get the conditional processing out of the way before the result of the conditional is expanded, thus ensuring that the result of the conditional sees the next bits in the stream and not the bits left lying around from the unfinished conditional.

1
  • Absolutely excellent answer - even I understand it. +1. Commented Apr 9, 2013 at 18:12
18

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.

15

The full context for such code is in conditional macros such as

\def\IfZero#1{%
  \ifnum0=#1\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}

The \expandafters are necessary if you look at the code in the less-formatted way:

\def\IfZero#1{\ifnum0=#1\relax\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}

(apologies for the long line) in which no clue is given as to the structure of the TeX conditional blocks. As you can see, the token "after" \@firstoftwo is \else, and that after \@secondoftwo is \fi, which are respectively expanded by \expandafter. The purpose of this silliness is that TeX doesn't read the entire conditional when it expands the \ifnum; it just scans forward to the correct true or false block and continues from there. The \else or \fi are left in the input stream! Once they are expanded, TeX scans to the end of the conditional and the next thing in the input stream is the stuff following \IfZero.

Without either \expandafter, the "two" consumed by \@firstoftwo and \@secondoftwo would be, respectively, \else\@secondoftwo and \fi and the following macro argument, rather than what is actually intended, namely the two following macro arguments that are taken as the "second" and "third" "arguments" of \IfZero.

1
  • By writing \ifnum#1=\z@ you avoid the need of \relax, making the macro \IfZero completely expandable. A minor point is that \else is not left in the input stream in case the conditional is false.
    – egreg
    Commented Apr 9, 2013 at 22:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .