Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
1  
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

1 Answer 1

up vote 11 down vote accepted

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...

share|improve this answer
    
@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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.