Expansion is often cited as one of the most arcane aspects of TeX, more akin to witchcraft than to something easily picked up by the newcomer. There are many great questions and great answers about expansion on the site but, although I like to think I'm getting better at it, I still find myself stumped by more complicated cases.
For instance, take the LaTeX internal called \in@
. Martin Scharrer's excellent List of internal LaTeX2e macros explains \in@
as follows:
\in@{⟨1⟩}{⟨2⟩}
Checks if first argument occurs in the second and sets the switch
\ifin@
accordantly. The arguments are not expanded. This must be done beforehand.
Because I'd like to pass once-expandable macros as arguments to \in@
, I need to expand each of those arguments once before \in@
gets expanded.
I managed to handle the case where the first argument needs to be expanded once and the second argument doesn't need expansion (see my code below).
However, I can't get my head around the \expandafter
juggling required to handle the case in which both arguments need to be expanded once. I think (correct me if I'm wrong) that I have to leave the braces untouched until \in@
itself is processed, and that's what I find difficult. I'd appreciate your help on this particular expansion problem.
\documentclass{article}
\let\ex=\expandafter % <--- more readable \expandafter
\begin{document}
\makeatletter
\in@{foo}{foo,bar,baz} % <--- works as expected
\ifin@ true\else false\fi
\def\foo{foo}
\ex\in@\ex{\foo}{foo,bar,baz} % <--- so far, so good...
\ifin@ true\else false\fi
\def\cslist{foo,bar,baz}
\in@{\foo}{\cslist} % <--- What combination of \expandafter is needed here?
\ifin@ true\else false\fi
\makeatother
\end{document}
However, more generally, I'd like to know what general procedure expansion gurus follow in their head (and possibly on paper) to expand a sequence of tokens in the desired order. Stephan v. Bechtolsheim's A tutorial on \expandafter
gave me some insight, but I'm still far from mastering it. I think sharing your tricks and recipes might help me and others improve our expansion skills.
So, what cognitive processes allow you to bend \expandafter
to your will?
Note: I insist on using only \expandafter
here, and none of that \edef
/ \noexpand
trickery. :)
Best Answer
If
\foo
is first expanded, then we have the problem, that\expandafter
cannot jump over serveral tokens at once, also the number of tokens is not known. Therefore the latest token is expanded first. But at this stage we cannot add the\expandafter
, because we have to insert the\expandafter
tokens for\foo
first:Then we add the outmost
\expandafter
chain to expand\cslist
. The next line uses\EX
for the new\expandafter
to make the difference between the stages visible:Result:
A more generic algorithm would be:
Establish an order of expansions:
Collapsing expansions: We have to make sure, that the number of tokens is known and we can insert
\expandafter
between them, if we need to jump over them. Therefore constructs like\csname
need to be expanded at an earlier level. This allows also the use of arguments inside\csname
with an unknown number of tokens, because the\csname
construct becomes one single command token after one expansion step.Note: See also the trick below, that
\csname
can be used to expand stuff afterwards.Expanding expansions, e.g.
\cslist
above, on the right side have to come first, because we cannot jump over a unknown number of tokens.Now we can add
\expandafter
chains from the start to the token that needs expanding. The order from the previous step is now reversed. First the chain for the token that is last expanded is inserted, e.g.:Then we go backwards in time to expand the token that needs expansion before the last:
"Tricks"
Sometimes TeX helps to save some
\expandafter
.Expanding after
\csname
:Let's assume
\foo
and\cslist
are not given explicitly but constructed via\csname
:A naive approach would require four expansions waves:
\csname
to get one token\foo
\csname
to get\cslist
\cslist
\foo
Result: Start with 24-1
\expandafter
(= 15).This can be reduced: TeX expands the tokens between
\csname
and\endcsname
until nothing expandable is left to form a command sequence. The following uses this to get\cslist
and its expansion before\foo
is constructed:And the whole expression with the expansion of
\foo
:The result are 15
\expandafter
in total.Expanding arguments of some TeX primitives such as
\uppercase
.Let's assume
\foo
expands to a word that should be converted to uppercase:Here we can save the first
\expandafter
, because\uppercase
already expands the next tokens until it gets the opening brace:Other primitives:
\detokenize
,\scantokens
,\message
.Caveat: If someone redefines
\uppercase
as macro, this trick will fail obviously.