# Curious effect with \newsavebox

The following code fails with the error

! LaTeX Error: Command \mybox already defined.
Or name \end... illegal, see p.192 of the manual.


despite the fact that \mybox has been relaxed.

\documentclass{minimal}
%
\newcommand{\repeatstuff}[1]{%
\newsavebox\mybox
\sbox\mybox{\ensuremath{\displaystyle #1}}
\usebox{\mybox}\usebox{\mybox}
\let\mybox\relax
}
%
\begin{document}
$\repeatstuff{\gamma} \repeatstuff{\alpha}$
$\repeatstuff{\gamma} \repeatstuff{\alpha}$
\end{document}


The problem only arises in the second equation, despite the fact that the first equation contains two instances of \repeatstuff. Can someone please explain this behaviour?

-
Thomson Every time you call \repeatstuff you call \newsavebox, hence the error. Move it outside the \newcommand. –  Yiannis Lazarides May 13 '11 at 16:20
@Yiannis --- why does the code work if you delete the second equation? Why doesn't relaxing \mybox prevent the error? –  Ian Thompson May 13 '11 at 16:28

EDIT: sorry, I thought about it. As others pointed out, the correct fix is to declare the box ouside the definition of \repeatstuff.

This can be fixed by replacing \let\mybox\relax by \global\let\mybox\relax. Assignments in TeX can be either "local", i.e., restricted to the current group (for instance the current environment in LaTeX, or within an equation, etc.), or "global", i.e., applied even outside the current group, everywhere.

When an assignment has been made locally within a group, the old value present before the group started is restored when the group ends. In your case, \newsavebox does a global assignment, because boxes are a scarce resource, that shouldn't be wasted, but \let\mybox\relax is local. Thus, the first \newsavebox defines \mybox globally, then it is locally let to \relax, which allows the second definition. When the equation ends, it is back to the former (globally assigned) value, namely, a box register. The third \newsavebox thus encounters an already defined command, and complains. Once more, \let\mybox\relax does its job locally, allowing the next \newsavebox, etc.

The following assignments are local:

• \def, \edef
• \let, \futurelet
• \chardef, \boxdef, \dimendef, \countdef, \toksdef
• \setbox
• \count123=... or \mycount=..., where \mycount is defined using \countdef (or \newcount, which is a wrapper around that, or \newcounter in LaTeX)
• other similar assignments with \toks, or \dimen, etc.
• etc.

All of those assignments can be made global by prefixing them with \global. As a convenience, TeX also provides \gdef and \xdef for \global\def and \global\edef, respectively.

Explaining why \newsavebox defines \mybox globally requires some discussion of how registers are allocated in plain TeX and in LaTeX...

-
@Bruno--- excellent, thanks! I'd completely overlooked the fact that \let\mybox\relax would only take effect locally. –  Ian Thompson May 13 '11 at 16:32
I should mention that the right solution is to declare the outside the command, not within it. –  Bruno Le Floch May 13 '11 at 16:41
what I needed was an explanation of what was going on, which is what your answer provided. I already knew that the problem would go away if I declared the box outside the macro. –  Ian Thompson May 13 '11 at 17:18