39

In Appendix D - Dirty Tricks Knuth gives an example of expanding four tokens in the right order by using eleven \expandafter commands. Here, is the code slightly adapted for to-morrow!

\tracingmacros=2  \tracingcommands=2
\def\z{M}
\def\Z{C}
\def\a{\z er}
\def\b{ry }
\def\c{\Z hr}
\def\d{ist}
\def\e{mas}

\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b\expandafter\c\d \e

\bye

This is in plain TeX, so you need to run it with pdfTeX. Why do we need 11 expandafters? Is there a rule of thumb for this type of definitions? How many do you need to expand five i.e, to expand \e also which I conveniently spaced out!

lockstep
  • 250,273
yannisl
  • 117,160
  • 10
    \expandafters tend to come in powers of two, minus one: one expandafter is "reach over token once", to reach over the token twice, you need thre:, the first jumps to the third, the third jumps over your token, leaving the second to jump over the second time, and so on. – Ulrich Schwarz Dec 24 '10 at 14:51
  • 2
    could one define a \superexpandafter{n} that would expand to 2^n-1 \expandafter's? – Yossi Farjoun Dec 24 '10 at 14:54
  • @Yossi. Only to some extent. You can do this if it is the first thing which needs to get expanded, but imagine \expandafter\SomeToken\superexpandafter{n}. You can't get the \superexpandafter to work 'as expected' here, as it would require at least two expansions to continue the chain past \SomeToken. – Joseph Wright Dec 24 '10 at 15:49
  • @Yiannis: By the way, there's no need for the two %. – Hendrik Vogt Dec 24 '10 at 16:53
  • @Hendrik You right I edited them out! – yannisl Dec 24 '10 at 19:40
  • @Yossi: If you post the question in your comment as a new question, then I think I do have an answer. (It's too long to put it here.) – Hendrik Vogt Jan 01 '11 at 12:51
  • @hendr: OK. will do. – Yossi Farjoun Jan 01 '11 at 17:35

2 Answers2

37

The short answer

Don't think of 11, but of 7+3+1 \expandafters. To also reach the \e, you'll need 15+7+3+1 \expandafters. As Ulrich says in his comment, these number are 2^4-1, 2^3-1 and so on.

What does \expandafter do?

The TeX primitive \expandafter steps over the token following it and once expands the next one. Since your macros \b, \c and \d don't take arguments, the code

\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b\expandafter\c\d\e

expands to

\expandafter\expandafter
\expandafter\a
\expandafter\b\c "\d, once expanded" \e

and this in turn to

\expandafter\a\b "\c, once expanded" "\d, once expanded" \e

to finally yield

\a "\b, once expanded" "\c, once expanded" "\d, once expanded" \e

With your definition of \a, \b and \c, you don't need all these \expandafters since those macros don't take any arguments. In fact, the above is an oversimplification: In the general case, if the macros do take arguments, the last line above would look somewhat like

\a \once{\b \once{\c \once{\d \e}}}

where \once is not a TeX command but should mean that the argument is expanded once, and the innermost expansion happens first, the outermost last. Here's a really stupid example:

\def\a#1.{#1}
\def\b#1:{#1.}
\def\c#1,{#1:}
\def\d{Hello world!,}
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b
\expandafter\c\d
\bye
\def

Firstly, \c replaces the , in Hello world!, with :. Secondly, \b replaces the : with ., and finally \a strips the .. In this example, all the \expandafters are needed.

What do 2^n-1 \expandafters do?

2^1-1=1 \expandafter expands the stuff after the next token once, and by induction you easily see that 2^n-1 \expandafters expand the stuff after the next token n times. Moreover, making this happen takes n expansion steps. Let's look again at your code, now from this point of view:

The first 7 \expandafters expand the stuff after \a 3 times. Two of these 3 expansion steps are needed to expand the 3 \expandafters after \a; let's keep in mind that a last expansion step is missing. Before that last step, the 3 \expandafters after \a expand the stuff after \b 2 times. The first expansion yields \c \once{\d \e} after the \b, the second one yields \once{\c \once{\d \e}}. This completes the description of two of these 3 expansion steps. In the third of these 3, the stuff after \a is expanded one last time.

In TH's comment, the 3 \expandafters expand the \csname bar\endcsname twice, thus yielding the expansion of \bar. Another important case is

\expandafter\def\expandafter\mycommand\expandafter{\somecontrolsequence}

This defines \mycommand as \somecontrolsequence, once expanded.

Another stupid example:

\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b\c

expands \c twice, thus expanding to something like

\a\b\twice{\c}
Hendrik Vogt
  • 37,935
25

To expand on the same theme as TH.'s comment to Hendrik's answer, when you must use lengthly \expandafter chains, you can exploit constructions like \csname...\endcsname (or, in some contexts, \number) which completely expand things by placing the right number of \expandafters just after/before the token you want to expand, e.g.

\csname macroone\expandafter\expandafter\expandafter\endcsname\macrotwo

will be the same as \macroone followed by \macrotwo expanded two times.

To give a concrete example, suppose you have \a\b\c\d\e and want to expand \e three times, \c two times, and \a, \b, \d one time. With the \csname...\endcsname method, it would be (here, we store the result of expansion inside a \temp macro and then \show it to see clearly what was expanded; you need the three \expandafter in the \def\temp because the first token needs two expansions):

\def\a{a}
\def\b{b}
\def\c{\C}\def\C{c}
\def\d{d}
\def\e{\E}\def\E{\ee}\def\ee{e}

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\csname a\expandafter\expandafter\expandafter\endcsname
\csname b\expandafter\expandafter\expandafter\expandafter
         \expandafter\expandafter\expandafter\endcsname
\csname c\expandafter\expandafter\expandafter\endcsname
\csname d\expandafter\expandafter\expandafter\expandafter
         \expandafter\expandafter\expandafter\endcsname
\e
}
\show\temp

\csname @@end\endcsname\bye % to work with both plain and LaTeX

To compare, here's the same version with chains of \expandafters:

\def\a{a}
\def\b{b}
\def\c{\C}\def\C{c}
\def\d{d}
\def\e{\E}\def\E{\ee}\def\ee{e}

\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\b
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\c
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\d
\e
}
\show\temp

\csname @@end\endcsname\bye % to work with both plain and LaTeX