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
\bf
is deprecated. Use either\bfseries
or\textbf{<text>}
instead.