Consider the following MWE:
\documentclass[12pt]{article}
\begin{document}
\def\aaa{something}
\typeout{=1==\aaa==}
\typeout{=1==\meaning\aaa==}
\typeout{}
\def\bbb{else \aaa, else}
\typeout{=2==\bbb==}
\typeout{=2==\meaning\bbb==}
\typeout{}
\def\ccc{third \bbb, level}
\typeout{=3==\ccc==}
\typeout{=3==\meaning\ccc==}
\typeout{}
\end{document}
It outputs the following to terminal:
=1==something==
=1==macro:->something==
=2==else something, else==
=2==macro:->else \aaa , else==
=3==third else something, else, level==
=3==macro:->third \bbb , level==
Thus, I'd consider (in this case) \meaning
to provide unexpanded contents of a macro (that would be "null" level of expansion); while \typeout
does "infinite" expansion (until no more tokens to be expanded). I've noted that \typeout
calls \write
:
$ texdef -t latex -c book -p titletoc typeout -f
\typeout is defined by (La)TeX.
\typeout:
macro:#1->\begingroup \set@display@protect \immediate \write \@unused {#1}\endgroup
… so this "infinite" expansion behavior may be due to \write
.
What I'd like, eventually, is an expandable function, which will accepts a numeric "level of expansion", and could be called like this:
# just a fake interface definition for testing
\def\expandlevel#1\nil#2\nil{
---#1---#2--
}
\edef\yyy{\expandlevel0\nil\ccc\nil}
\typeout{\yyy}
… such that:
- When I call for level null expansion – what I get when I typeout are unexpanded contents (like
\meaning
); pseudo:* \typeout{==\expandlevel0\nil\ccc\nil==} ==third \bbb , level==
- When I call for a single expansion – what I get is (pseudo):
* \typeout{==\expandlevel1\nil\ccc\nil==} ==third else \aaa , else , level==
- When I call for infinite expansion – that would be 99 levels
:)
– what I get is the same as\typeout
would perform; pseudo:* \typeout{==\expandlevel99\nil\ccc\nil==} ==third else something, else, level==
Unexpandable/protected tokens would remain (or be shown with \inaccessible
), as \typeout
performs currently..
In lack of a "real" expandable macro like that, are there any tricks to coax \typeout
to behave in similar fashion (if possible)?
Best Answer
This has nothing to do with
\typeout
except insofar as its argument is fully expanded because of\write
, as you noted. You could ask the same of\edef
, and the answer would be to use a sufficiently elaborate combination of\expandafter
,\noexpand
, and\unexpanded
to force each token to expand the desired number of times. For example:The number of
\expandafter
s increases exponentially. The question of how to write a single expandable command that expands the desired number of times is addressed here. Note that the answer given there still only expands one token, so you can't apply it to an entire text. It is possible to play tricks with\unexpanded
(a\noexpand
for many tokens) and with token list registers (which, inside\edef
, expand to their contents and then make the result temporarily unexpandable) to achieve similar effects.You might be wondering, if zero expansions and infinite expansions are allowed on an entire text, why not one or more? The answer is that in fact, "infinite" expansions are done token-by-token and there is no notion of expanding the "whole text". To do zero expansions TeX simply has to dump the token list as given; the way that
\meaning
apparently does one expansion is that it actually changes the\catcode
s of its output so that it is no longer expandable: those aren't real macros you see. You can achieve the same effect yourself if you use\scantokens
in combination with a\catcode
change...except that\catcode
is not expandable, so you can't do that in\edef
or\write
. Or rather, if you do, you will just see the string "\catcode
" in the result.Anyway, if you want to expand a "whole text" a certain number of times, you could mean one of three things:
Expand the first token, and then expand the first token of the result, and so on, that many times.
Expand the first expandable token, then the first expandable token of the result, and so on, that many times.
Expand the first expandable token; then, in the expanded text, expand everything (n - 1) times in the same way. Once you're done, move to the first "untouched" token and continue in this way to the end of the text. (Thus, expanding to a certain "depth" across the entire text.)
Rules 1 and 2 have different results:
where expanding "once" gives either "a
\a
" or "aa" depending on the rule. Rule 1 is relatively easy to implement using\multiexpandafter
(from the other question) and\unexpanded
. Rule 2 is probably impossible without embedding\expandafter
and\noexpand
into all your macros. Rule 3 is probably Turing-complete.