5

The answer here may be obvious but I can't find it. I use \newsavebox in many routines and for different purposes. These are saved globally and I guess are a reasonably precious resource.

In all instances the box is used for a variety of purposes immediately after content is saved in the box. I don't care about overwriting previous box content (which can be large).

I decided, to save resources to use the same box for many different things

\newsavebox{\mybox}

I don't know in advance which particular routines I am going to need for a particular document, and I don't want to declare a common box outside of the source for each box use. Consequently there are several declarations of \newsavebox{\mybox} (or none at all depending what I am doing).

Bottom line, how can I test for the existence of \mybox before re-creating it? MWE is:

\documentclass{article}
\newsavebox{\mybox}
\newsavebox{\mybox}
\begin{document}
\end{document}
Tonechas
  • 976
  • "and I don't want to declare a common box outside of the source for each box use." why not? that is exactly the intended use. It is normally a mistake to have the \newxxx command in a command that is used more than once. plain tex goes to the extreme of declaring \newbox to be \outer so that using in in another definition is an error. – David Carlisle Jan 19 '16 at 19:25
  • I agree with that. I think you misunderstood what I meant - I have several sets of code that do different things (generally just imported into my preamble) - each of those uses a box and declares it - and oftentimes it is the same box (not declaring new boxes within commands at all). – Aubrey Blumsohn Jan 19 '16 at 21:40
  • Ah OK, in that case really you could just allocate a different box to each set there are 32000 of them available these days with etex, it's not like classic tex when there were only 256. – David Carlisle Jan 19 '16 at 21:56
  • My anxiety was that each box might contain a large bit of detritus (a very large tikz or other image) as well as using an allocation slot. But perhaps the former is not a problem (mindset is that of someone bred in 1980 with an expensive 10Mb external drive). – Aubrey Blumsohn Jan 20 '16 at 11:08

3 Answers3

7

A box defined defined with \newsavebox is basically nothing else than a wrapper command name for the corresponding box register. Checking for the macro name would do, e.g. with \@ifundefined.

\documentclass{article}
\newsavebox{\mybox}

\makeatletter
\@ifundefined{mybox}{%
  \newsavebox{\mybox}%
}{}
\makeatother


\begin{document}
Foo
\end{document}
3

The LaTeX kernel provides a similar approach when working with regular macros through \providecommand{<cs>}. If <cs> already exists, nothing happens*, otherwise, \providecommand acts just like \newcommand. One can copy this approach to create \providesavebox:

abc
def

\documentclass{article}

\makeatletter
\newcommand{\providesavebox}[1]{%
  \begingroup
    \escapechar\m@ne\xdef\@gtempa{{\string#1}}%
  \endgroup
  \expandafter\@ifundefined\@gtempa
    {\newsavebox#1}%
    {}%
}
\makeatother

\begin{document}

\providesavebox{\mybox}
\savebox{\mybox}{abc}
\usebox{\mybox}

\providesavebox{\mybox}
\savebox{\mybox}{def}
\usebox{\mybox}

\end{document}

Of course, alternatives to the above also exist, since boxes are referenced in the same way we reference macros. As such, you can also use some of the e-TeX conditionals provided in How to conditionally define a new command in LaTeX?.

* Actually, the scratch macro \@reserveda is redefined instead of the provided macro name.

Werner
  • 603,163
3

As an alternative, the stackengine package provides a command \savestack{<name>}{<box content>} that places content in a saved box. However, instead of using \usebox to recall it, one merely invokes the macro name to recall the box.

If one looks under the hood, the invocation \savestack{\mybox}{<content>} actually places <content> into a box named \myboxcontent. And the macro \mybox is merely set to \usebox{\myboxcontent} as shown in the MWE. Internally, it uses \@ifundefined to determine if it needs to create the box or not.

\documentclass{article}
\usepackage{stackengine}
\begin{document}
\savestack{\mybox}{A}
\mybox\par
\savestack{\mybox}{B}
\mybox{} is the same as \usebox{\myboxcontent}
\end{document}

enter image description here