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}
  • "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
6

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

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

2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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