# Create a \savebox in a Group and have it available outside of group

The MWE below creates a \savebox within a group which results in several blank lines:

If I comment out the\begingroup and \endgroup I get the desired results:

My thinking was that adding the \global should have fixed this issue.

So, how do I create and define \savebox within a group and yet be able to use the outside of the group?

## Notes:

• While the MWE here does not need grouping my actual use case does, so I would really prefer to not have to eliminate the grouping.

## Code:

\documentclass{article}
\usepackage{etoolbox}

\begingroup
\ifcsdef{MyBox #1-#2}{%
}{%
\typeout{*** Defined savebox for #1-#2}%
\global\expandafter\newsavebox\csname MyBox #1-#2\endcsname%
\global\expandafter\savebox\csname MyBox #1-#2\endcsname{#2: #1}%
}%
\expandafter\usebox\csname MyBox #1-#2\endcsname%
\endgroup
}%

\begin{document}

\end{document}

• why a box here (allocating a box every use is not usually recommended, even though etex means you have rather more than in classic tex) – David Carlisle Dec 16 '15 at 12:10
• \global\savebox is definitely not going to work. – egreg Dec 16 '15 at 12:13
• @DavidCarlisle: My actual use case is more involved, so the reason is for efficiency to save doing things thousands of times. – Peter Grill Dec 16 '15 at 12:13
• @PeterGrill are you sure it's that much more efficient than a macro? – David Carlisle Dec 16 '15 at 12:18
• @DavidCarlisle: Just did a small test. Using the solution you posted required less than 1/3 the elapsed time. – Peter Grill Dec 16 '15 at 12:33

I suspect that using a locally allocated box here is the wrong thing to do but to do it, just use the primitive commands to set the content:

\documentclass{article}
\usepackage{etoolbox}

\begingroup
\ifcsdef{MyBox #1-#2}{%
}{%
\typeout{*** Defined savebox for #1-#2}%
\global\expandafter\newsavebox\csname MyBox #1-#2\endcsname%
\global\expandafter\setbox\csname MyBox #1-#2\endcsname\hbox{{#2: #1}}%
}%
\expandafter\usebox\csname MyBox #1-#2\endcsname%
\endgroup
}%

\begin{document}

\end{document}


Let's see what \global\savebox\foo does:

1. \global expands \savebox so the input stream is

\global\@ifnextchar ({\@savepicbox \foo}{\@ifnextchar [{\@savebox #1}{\sbox \foo}}

2. \global expands \@ifnextchar, so the input stream is

\global\let\reserved@d=( [...]


(where [...] denote irrelevant tokens).

3. \global is applied to \let.

Note that \global doesn't disappear until it finds a token it can apply to (\def, \let, a register address and so on; in general, an assignment).

This explains why you don't get errors, but also why you don't get a global setting for your box.

Doing \global\sbox\foo{tokens} would work, because the first expansion step triggered by \global is

\global\setbox\foo\hbox{\color@setgroup tokens\color@endgroup}


However, you may be using a stripped down example and perhaps you need the full force of \savebox, instead of \sbox, so you can use a temporary box register for the construction and then globally set the new register to be the same as the built box.

\documentclass{article}
\usepackage{etoolbox}

\begingroup
\ifcsdef{MyBox #1-#2}{%
}{%
\typeout{*** Defined savebox for #1-#2}%
\global\expandafter\newsavebox\csname MyBox #1-#2\endcsname
}%
\expandafter\usebox\csname MyBox #1-#2\endcsname
\endgroup
}

\begin{document}


• Yes, example is heavily stripped down, but I am not sure I know what the "full force of \savebox" is. Is there a question here that explains what \savebox will do that \sbox can't? – Peter Grill Dec 16 '15 at 12:37
• @PeterGrill \savebox accepts optional arguments the same way as \makebox does (after the mandatory first argument to \savebox, of course). So you can do \savebox{\foo}[2\width][l]{...}, for instance. – egreg Dec 16 '15 at 12:39