LaTeX forum ⇒ GeneralQuestion 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

Question about expandafter chains...

Postby kreyszig » Wed Jan 27, 2010 4:59 am

Hello,

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

  1. \def\hello#1{Hello #1}%
  2. \def\world{World}%
  3. \expandafter\def\expandafter\msg\expandafter{\expandafter\hello\world}%
  4. \show\def%


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


but I was expecting it to be
  1. > \msg=macro:
  2. ->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

Postby josephwright » Wed Jan 27, 2010 9:04 am

After TeX has followed your \expandafter run, you end up with
  1. \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
  1. \edef\msg{%
  2. \expandafter\unexpanded\expandafter{\hello}%
  3. \expandafter\unexpanded\expandafter{\world}%
  4. }

Here the \expandafter instructions do one level expansion, while the \unexpand's prevent any further expansion. Without e-TeX, you could use token registers:
  1. \newtoks\toksa
  2. \newtoks\toksb
  3. \toksa\expandafter{\hello}
  4. \toksb\expandafter{\world}
  5. \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

Postby phi » Wed Jan 27, 2010 1:25 pm

josephwright wrote:After TeX has followed your \expandafter run, you end up with
  1. \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
  1. \edef\msg{%
  2. \expandafter\unexpanded\expandafter{\hello}%
  3. \expandafter\unexpanded\expandafter{\world}%
  4. }

Here the \expandafter instructions do one level expansion, while the \unexpand's prevent any further expansion. Without e-TeX, you could use token registers:
  1. \newtoks\toksa
  2. \newtoks\toksb
  3. \toksa\expandafter{\hello}
  4. \toksb\expandafter{\world}
  5. \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:
  1. \documentclass{minimal}
  2.  
  3. \begin{document}
  4.  
  5. \ttfamily
  6.  
  7. \def\hello#1{Hello #1}%
  8. \def\world{World}%
  9.  
  10. \expandafter\expandafter\expandafter\def
  11. \expandafter\expandafter\expandafter\msg
  12. \expandafter\expandafter\expandafter{%
  13. \expandafter\hello\expandafter{\world}%
  14. }
  15. \meaning\msg
  16.  
  17. \edef\msg{\hello\world}
  18. \meaning\msg
  19.  
  20. % \edef\msg{%
  21. % \expandafter\unexpanded\expandafter{\hello}%
  22. % \expandafter\unexpanded\expandafter{\world}%
  23. % }
  24. % \meaning\msg
  25.  
  26. % \newtoks\toksa
  27. % \newtoks\toksb
  28. % \toksa\expandafter{\hello}
  29. % \toksb\expandafter{\world}
  30. % \edef\msg{\the\toksa\the\toksb}
  31. % \meaning\msg
  32.  
  33. \end{document}

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

Postby kreyszig » Wed Jan 27, 2010 4:26 pm

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

Postby kreyszig » Wed Jan 27, 2010 4:45 pm

phi wrote:After TeX has
  1. \documentclass{minimal}
  2.  
  3. \begin{document}
  4.  
  5. \ttfamily
  6.  
  7. \def\hello#1{Hello #1}%
  8. \def\world{World}%
  9.  
  10. \expandafter\expandafter\expandafter\def
  11. \expandafter\expandafter\expandafter\msg
  12. \expandafter\expandafter\expandafter{%
  13. \expandafter\hello\expandafter{\world}%
  14. }
  15. \meaning\msg
  16.  
  17. \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

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


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

josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Postby josephwright » Wed Jan 27, 2010 5:33 pm

I dodn't follow. If you avoid wrapping the expansion of \world in braces, then what is wrong with
  1. \documentclass{minimal}
  2.  
  3. \begin{document}
  4.  
  5. \ttfamily
  6.  
  7. \def\hello#1 #2{Hello #1:#2:}%
  8. \def\world{World}%
  9.  
  10. \expandafter\expandafter\expandafter\def
  11. \expandafter\expandafter\expandafter\msg
  12. \expandafter\expandafter\expandafter{%
  13. \expandafter\hello\world
  14. }
  15. \meaning\msg
  16.  
  17. \end{document}
Joseph Wright

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

Postby kreyszig » Wed Jan 27, 2010 5:58 pm

josephwright wrote:I dodn't follow. If you avoid wrapping the expansion of \world in braces, then what is wrong with
  1. \documentclass{minimal}
  2.  
  3. \begin{document}
  4.  
  5. \ttfamily
  6.  
  7. \def\hello#1 #2{Hello #1:#2:}%
  8. \def\world{World}%
  9.  
  10. \expandafter\expandafter\expandafter\def
  11. \expandafter\expandafter\expandafter\msg
  12. \expandafter\expandafter\expandafter{%
  13. \expandafter\hello\world
  14. }
  15. \meaning\msg
  16.  
  17. \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

Postby phi » Wed Jan 27, 2010 5:59 pm

josephwright wrote:I dodn't follow. If you avoid wrapping the expansion of \world in braces, then what is wrong with
  1. \documentclass{minimal}
  2.  
  3. \begin{document}
  4.  
  5. \ttfamily
  6.  
  7. \def\hello#1 #2{Hello #1:#2:}%
  8. \def\world{World}%
  9.  
  10. \expandafter\expandafter\expandafter\def
  11. \expandafter\expandafter\expandafter\msg
  12. \expandafter\expandafter\expandafter{%
  13. \expandafter\hello\world
  14. }
  15. \meaning\msg
  16.  
  17. \end{document}

This doesn't even compile because the replacement text of \world should contain a space. If you say
  1. \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.
  1. \documentclass{minimal}
  2.  
  3. \begin{document}
  4.  
  5. \ttfamily
  6.  
  7. \def\hello#1 #2\nil{Hello #1:#2:}%
  8. \def\world{The World}%
  9.  
  10. \expandafter\expandafter\expandafter\def
  11. \expandafter\expandafter\expandafter\msg
  12. \expandafter\expandafter\expandafter{%
  13. \expandafter\hello\world\nil
  14. }
  15. \meaning\msg
  16.  
  17. \end{document}

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

Postby kreyszig » Wed Jan 27, 2010 6:06 pm

ok,

I have found a solution that works:

  1. \def\hello#1 #2{Hello #1 #2}%
  2. \def\world{{The} {World}}%
  3.  
  4. \def\exec#1#2{\expandafter\def\expandafter\result\expandafter{#1#2}}%
  5. \expandafter\exec\expandafter\hello\expandafter{\world}%
  6.  
  7. \show\result


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

josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Postby josephwright » Wed Jan 27, 2010 7:57 pm

phi wrote:
This doesn't even compile because the replacement text of \world should contain a space.

Mu apologies: I of course meant
  1. \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


Return to “General”

Who is online

Users browsing this forum: No registered users and 5 guests