[Tex/LaTex] Problem with nested \noexpand and \edef

expansionmacros

I have a LaTeX problem and want to explain it with the following code snippet:

\documentclass{article}
\begin{document}

  \def\myline{A}
  \edef\myline{\myline \noexpand\bf B}
  \edef\myline{\myline C}

  \myline
\end{document}

I have to build up a line incrementally. This happens inside of a for loop.
The problem is that I want to highlight some text in bold, but whenever I expand my line, I get the following error:

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
l.9 \myline

? X

I think, it is because of the third \edef, which tries to expand the \bf in the second \edef, however I have to expand it to avoid infinite recursion.

Best Answer

Let's see what happens

\def\myline{A}
\edef\myline{\myline \noexpand\bf B}

Given the first line, the second is equivalent to

\def\myline{A\bf B}

Now, when you say

\edef\myline{\myline C}

TeX expands the inner \myline completely and this is what it becomes (result of \show\myline edited to avoid bad line breaks):

> \myline=macro:
->A\protect \protect \protect \edef OT1{OT1}\let \enc@update \relax
 \protect \edef cmr{cmr}\protect \edef m{m}\protect \edef n{n}
 \protect \xdef \OT1/cmr/m/n/10 {\OT1/cmr/m/n/10 }\OT1/cmr/m/n/10
 \size@update \enc@update \ignorespaces \relax \protect \relax 
 \protect \edef m{bx}\protect \xdef \OT1/cmr/m/n/10  
 {\OT1/cmr/m/n/10}\OT1/cmr/m/n/10 \size@update \enc@update BC.

which is surely not what TeX likes to see when executing the newly defined \myline.

The problem is that \noexpand inhibits expansion once: in the second \edef, the token \bf will be expanded. This is a "correct" way to proceed:

\documentclass{article}
\begin{document}

\makeatletter
\def\myline{A}
\protected@edef\myline{\myline \bfseries B}
\protected@edef\myline{\myline C}

\myline
\end{document}

Note that \protect in front of \bfseries is not needed, as \bfseries is already a "LaTeX robust command".

Another way is to use etoolbox:

\documentclass{article}
\usepackage{etoolbox}
\robustify\bfseries

\begin{document}

\def\myline{A}
\edef\myline{\myline \bfseries B}
\edef\myline{\myline C}

\myline
\end{document}

This will make \bfseries "protected forever" inside an \edef.

Martin suggests in his answer to use \appto, which is quite a good way to build a macro by accretion:

\usepackage{etoolbox}

\def\myline{}
\appto\myline{A \bfseries B}
\appto\myline{C}

In this case we get the same result as

\def\myline{A \bfseries BC}

If the accretion has to be global, you can use \gappto (which is equivalent to the kernel macro \g@addto@macro).

Another strategy is to use token registers:

\newtoks\mylinetoks

\mylinetoks={}
\mylinetoks={A \bfseries B}
\mylinetoks=\expandafter{\mylinetoks C}

Of course the register can be used as many times as one likes, it's necessary to allocate it only once. The kernel provides \addto@hook:

\newtoks\mylinetoks

\makeatletter
\mylinetoks={}
\addto@hook\mylinetoks{A \bfseries B}
\addto@hook\mylinetoks{\mylinetoks C}

For using the contents of the register, you say

\the\mylinetoks
Related Question