The explanation will need a bit of TeX theory.
A group is a part of the document that confines most changes made inside it only to this group itself. That is, most settings changed inside a group will be reverted to their old values once the group ends. A group is delimited by { … }
or \begingroup … \endgroup
. For example, a command \itshape
switches the font shape to italic. If it is used in the document, all text after that point will be set in italic shape (unless another command switches the font again). But when used inside a group — {\itshape test}
— its effect will only last to the end of the group; when the group ends, the font will be restored to whatever it was before the group was started. If an assignment or a macro definition should transcend any groups it might be in and remain in effect after the groups end, it must be prefixed with \global
(this only works for primitive TeX operations).
Replacing a macro with its replacement text is called expanding the macro. TeX expands macros as it reads the input, but it does not necessarily expand arguments to commands — they are passed as they are. Therefore, in
\def\a{a}
\def\b{b \a}
(\def
is the TeX primitive for defining new macros), the replacement text for \b
is b \a
, not b a
. Only when \b
is used, \a
will be expanded recursively. If it is needed that \a
is expanded at the time of \b
definition, there exists a similar primitive to \def
— \edef
, which fully (that is, recursively) expands the to-be replacement text and only then associates the text with the macro name.
Now let's look at the code.
It cannot be seen directly, but the iteration code in \foreach
is processed inside a group. Therefore, the result of \renewcommand
is immediately forgotten after each iteration, and in the end \myresult
is still empty. We can remedy this by using \global\def
instead of \renewcommand
(\renewcommand
is a complex macro and won't be affected by \global
):
\global\def\myresult{blah \myresult}
But now we get a different problem. After at least one iteration, \myresult
now has the replacement text blah \myresult
. If TeX encounters \myresult
in input, it will replace the macro with blah \myresult
, which it will replace then with blah blah \myresult
, … until there is no more memory left. The problem is that we caused an infinite recursion by defining a macro that expands to itself. We wanted to use the old value of \myresult
when we redefined it, but ended up using the macro itself. We already know that we can use \edef
instead of \def
to do the former instead of the latter. Now the relevant line becomes
\global\edef\myresult{blah \myresult}
Plain TeX defines \xdef
to be \global\edef
. So we can shorten the code:
\xdef\myresult{blah \myresult}
Now it will work as planned.
With all this explained, package etoolbox
provides the commands \xpreto<hook>{<code>}
and \xappto<hook>{<code>}
, which will globally prepend or append the expansion of code
to the definition of <hook>
. I should also note that spaces and new lines are significant to TeX and the code needs some comment characters.