## LaTeX forum ⇒ General ⇒ Question about expandafter chains...

LaTeX specific issues not fitting into one of the other forums of this category.
kreyszig
Posts: 11
Joined: Tue Jan 26, 2010 4:30 am

Hello,

could someone explain to me why in the following code the macro \msg is not defined as "Hello World"

\def\hello#1{Hello #1}%\def\world{World}%\expandafter\def\expandafter\msg\expandafter{\expandafter\hello\world}%\show\def%

The output is
> \msg=macro:->\hello World.

but I was expecting it to be
> \msg=macro:->Hello World.

So \hello is not expanded as I was expecting.

I need a single level expansion of both \world and \hello and the the expansion of \world to be used as argument of \hello.

Thanks!

Tags:

josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm
After TeX has followed your \expandafter run, you end up with
\def\msg{\hello world}%

which then gives the definition you see. This is is because \def does no expansion, and your \expandafter run only affects \world.

If we assume you have e-TeX available, then you can do
\edef\msg{%   \expandafter\unexpanded\expandafter{\hello}%   \expandafter\unexpanded\expandafter{\world}%}

Here the \expandafter instructions do one level expansion, while the \unexpand's prevent any further expansion. Without e-TeX, you could use token registers:
\newtoks\toksa\newtoks\toksb\toksa\expandafter{\hello}\toksb\expandafter{\world}\edef\msg{\the\toksa\the\toksb}

but this is obviously more awkward (especially as the number of items grows).
Joseph Wright

phi
Posts: 577
Joined: Tue Oct 21, 2008 8:10 pm
josephwright wrote:After TeX has followed your \expandafter run, you end up with
\def\msg{\hello world}%

which then gives the definition you see. This is is because \def does no expansion, and your \expandafter run only affects \world.

If we assume you have e-TeX available, then you can do
\edef\msg{%   \expandafter\unexpanded\expandafter{\hello}%   \expandafter\unexpanded\expandafter{\world}%}

Here the \expandafter instructions do one level expansion, while the \unexpand's prevent any further expansion. Without e-TeX, you could use token registers:
\newtoks\toksa\newtoks\toksb\toksa\expandafter{\hello}\toksb\expandafter{\world}\edef\msg{\the\toksa\the\toksb}

but this is obviously more awkward (especially as the number of items grows).
Your suggestions don't work here because \hello is itself a macro with a parameter. Here we either need two \expandafter chains or exhaustive expansion:
\documentclass{minimal} \begin{document} \ttfamily \def\hello#1{Hello #1}%\def\world{World}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\msg\expandafter\expandafter\expandafter{%   \expandafter\hello\expandafter{\world}%}\meaning\msg \edef\msg{\hello\world}\meaning\msg % \edef\msg{%%   \expandafter\unexpanded\expandafter{\hello}%%   \expandafter\unexpanded\expandafter{\world}%% }% \meaning\msg % \newtoks\toksa% \newtoks\toksb% \toksa\expandafter{\hello}% \toksb\expandafter{\world}% \edef\msg{\the\toksa\the\toksb}% \meaning\msg \end{document}

kreyszig
Posts: 11
Joined: Tue Jan 26, 2010 4:30 am
Thanks! I think I get the idea now. I was somehow misleaded by expandafter definition that says that

\expandafter\a\b

"expands \b, then \a". A more correct statement I think would be that it expands \b than put \a back in front of it, not preventing it from being expanded. What I mean is that expandafter does not itself expands \a, right?

Thanks!

kreyszig
Posts: 11
Joined: Tue Jan 26, 2010 4:30 am
phi wrote:After TeX has
\documentclass{minimal} \begin{document} \ttfamily \def\hello#1{Hello #1}%\def\world{World}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\msg\expandafter\expandafter\expandafter{%   \expandafter\hello\expandafter{\world}%}\meaning\msg \end{document}

I am afraid this does not work either for the more general case where \hello can take more arguments, for example if it is defined as

\def\hello#1 #2{Hello #1 #2}

and that \world is defined as
\def\world{The World}

josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm
I dodn't follow. If you avoid wrapping the expansion of \world in braces, then what is wrong with
\documentclass{minimal} \begin{document} \ttfamily \def\hello#1 #2{Hello #1:#2:}%\def\world{World}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\msg\expandafter\expandafter\expandafter{%   \expandafter\hello\world}\meaning\msg \end{document}
Joseph Wright

kreyszig
Posts: 11
Joined: Tue Jan 26, 2010 4:30 am
josephwright wrote:I dodn't follow. If you avoid wrapping the expansion of \world in braces, then what is wrong with
\documentclass{minimal} \begin{document} \ttfamily \def\hello#1 #2{Hello #1:#2:}%\def\world{World}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\msg\expandafter\expandafter\expandafter{%   \expandafter\hello\world}\meaning\msg \end{document}

yes I agree that not using the braces does not work either. What I meant is that the code with the braces only works if the \hello command only takes a single argument...

phi
Posts: 577
Joined: Tue Oct 21, 2008 8:10 pm
josephwright wrote:I dodn't follow. If you avoid wrapping the expansion of \world in braces, then what is wrong with
\documentclass{minimal} \begin{document} \ttfamily \def\hello#1 #2{Hello #1:#2:}%\def\world{World}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\msg\expandafter\expandafter\expandafter{%   \expandafter\hello\world}\meaning\msg \end{document}

This doesn't even compile because the replacement text of \world should contain a space. If you say
\def\world{The World}
the result is "Hello The:W:orld", while the OP probably wants "Hello The:World:". Here you need another delimiter, e.g.
\documentclass{minimal} \begin{document} \ttfamily \def\hello#1 #2\nil{Hello #1:#2:}%\def\world{The World}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\msg\expandafter\expandafter\expandafter{%   \expandafter\hello\world\nil}\meaning\msg \end{document}

kreyszig
Posts: 11
Joined: Tue Jan 26, 2010 4:30 am
ok,

I have found a solution that works:

\def\hello#1 #2{Hello #1 #2}%\def\world{{The} {World}}% \def\exec#1#2{\expandafter\def\expandafter\result\expandafter{#1#2}}%\expandafter\exec\expandafter\hello\expandafter{\world}% \show\result

> \result=macro:
->Hello The World.

josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm
phi wrote:
This doesn't even compile because the replacement text of \world should contain a space.

Mu apologies: I of course meant
\def\hello#1#2{Hello #1:#2:}%

which then does work to give the expected "Hello W:o:rld" (i.e. each token collected separately).
Joseph Wright