41

I'm aware that some "temporary" LaTeX dimensions etc. exist. I would, however, like to know all of them.

I know \reserved@a (macro), \@tempdima (dimension) and \@tempcnta (counter).

1
  • 9
    The \reserved@... set are not really 'temporary' in the same sense as \@tempa or \@tempdima: the reserved is there for a reason (team use only)!
    – Joseph Wright
    Dec 26, 2012 at 21:23

3 Answers 3

31

The use of scratch registers and macros in TeX/LaTeX date back to the time when it was absolutely essential to conserve memory consumption, because TeX's memory (both in terms of token/macro memory as well as number of available registers) was very limited and one could easily run out of space just by loading a few packages on top of the main format.

Traces of this can be still found all over the place in the code, e.g., you see things like \@plus as an abbreviation for the 5 tokens plus so that each time this was needed in code you would save 4 tokens. The same is true for registers which were limited to a total number of 256 of each type and loading, say pictex could already get you close to the total limits in available count and dimen registers.

However, using scratch registers and macros to overcome these limitations always came with a price: there is always the danger that the register or macro got reused while your code is still assuming that it holds your value! And despite a lot of precautions (like using them only within a group or ensure that setting and use would be really really next to each other) time and time again it caused bugs and issues because macros got called within arguments of others (both assuming that they could safely use the same scratch object) or through the fact that the output routine is visited in unexpected situations changing the context.

With LaTeX2e which was born 1994 or so the size limitation got even worse because the core code got extended. So we had to use scratch registers all over the place and conserve memory as best as we could. But knowing the issues with them we split the scratch registers into two: those that we wanted to see only being used within kernel code and those that had been used in the past by third party packages already (and which we couldn't take away without breaking those package). Therefore we introduced \reserved@... hoping that the name clearly indicates that they are not intended for use by package authors.

Bottom line: use of scratch registers and macros is not advisable unless there is a very good reason and these days the original reason (the memory limitation) is no longer valid. All modern TeX installations (younger than a decade or so) these days are based on eTeX and all offer enough space and registers that it is much better and simpler if packages use their own private commands and registers and therefore can rely on living side by side without any headache.

With LaTeX3 (expl3) we recommend not to use any scratch registers at all even though we do offer a few as we know that old habits do not die easily.

5
  • 2
    My view on the scratch variables in expl3 is that they are useful for quick 'in document' stuff (truly localised to one use case), but should not be used in anything produced as a package or class.
    – Joseph Wright
    Dec 27, 2012 at 10:26
  • 4
    @Stephen ... all in all modern ones ;-) in TeX terms a decade is modern, ok? Dec 27, 2012 at 22:45
  • @FrankMittelbach: What about the commercial ones that are still around? Does e.g. BaKoMa support eTeX? Dec 27, 2012 at 22:58
  • 1
    @Martin ... pdfTeX with eTeX extension was becoming the main engine in the communitiy distributions when? sometimes in the '90s and at some point in the last decade LaTeX officially stated that eTeX has to be supported in the underlying engine to successfully run LaTeX. Sure there might be implementations out there .. Anyway, all I was describing was the history of why the scratch register where important, if somebody is really still on such a TeX there will be a lot of limitations like that ... and if the engine is 10-15 years old I think it is fair not to call it "modern" ok? Dec 27, 2012 at 23:12
  • I'm fine with "modern", thanks for the edit!
    – Stephen
    Dec 28, 2012 at 17:11
38

The LaTeX kernel allocates some scratch registers and defines a scratch conditional. The complete list is

\newcount\@tempcnta
\newcount\@tempcntb
\newif\if@tempswa
\newdimen\@tempdima
\newdimen\@tempdimb
\newdimen\@tempdimc
\newbox\@tempboxa
\newskip\@tempskipa
\newskip\@tempskipb
\newtoks\@temptokena

Notice that for the first two \newcount is used, rather than \newcounter. All these registers and \if@tempswa (with the companion macros \@tempswatrue and \@tempswafalse) must be used only locally, so never assigned values with the \global prefix.

The register allocation mechanism always leaves free the first ten register numbers, so also

\dimen0 ... \dimen9
\skip0 ... \skip9
\toks0 ... \toks9

and box registers 0 to 9 are free for scratch usage. An agreed upon convention (that unfortunately some packages don't follow) is that even numbered scratch registers should be used locally, and odd numbered ones should be used globally. Also for local usage are

\count@
\dimen255
\skip255
\toks255

but not box register 255; \count@ is an alias for \count255, actually, while \dimen@, \skip@ and \toks@ stand for the 0 register of each type.

The kernel uses also \reserved@a, \reserved@b, \reserved@c, \reserved@d and \reserved@e as scratch macros, but apart from special tasks, it's better not using them in packages or personal macros. The macro \@gtempa is used as "global scratch macro" and its meaning should always be set globally.

Also registers \muskip0 to \muskip9 are available as scratch registers, but I don't know of any packages that uses them.

Usage of scratch conditional and registers should follow some simple rules.

  1. Never rely on their value before using them, therefore initialize their value at the start of the job.

  2. Avoid calling macros that might use the same scratch registers during the time you need those register to have a relied upon value, unless the call is made inside a group, so that the previous value will be restored at group end.

  3. In case of doubt, don't use scratch registers, but allocate your own.

Any register can be used as scratch register, provided this is done inside a group and following the rules above (but with more care about possible value clobbering). So it's fairly common to find \count0 and \count2 used as scratch registers inside a group; this is safe, provided nothing that can trigger a page break is performed. Why? The value of the counters \count0 to \count9 is recorded in the DVI or PDF output during a \shipout operation (if nonzero, for the registers numbered 1 to 9); the LaTeX counter page is actually \count0.


A very common pitfall is in the usage of box registers which do follow the group structure, with the peculiarity that \box and \unhbox destroy the current incarnation of the box register. So, after

\setbox0=\hbox{foo}\begingroup\box0\endgroup

the box register 0 will be void. On the other hand,

\setbox0=\hbox{foo}\begingroup\setbox0=\hbox{bar}\box0\endgroup

will result in box register 0 still containing \hbox{foo}.

10

This might only be a partial answer, depending on your view of other packages that might also define scratch registers/variables.

Searching latex.ltx you'll find a number of temporary things (actually defined in ltalloc.dtx):

\newcount\@tempcnta
\newcount\@tempcntb
\newdimen\@tempdima
\newdimen\@tempdimb
\newdimen\@tempdimc
\newbox\@tempboxa
\newskip\@tempskipa
\newskip\@tempskipb
\newtoks\@temptokena

There's also \newif\if@tempswa, but this falls under the same umbrella as \@reserved@..., as commented by Joseph.

7
  • You might want to include for example \toks@ (\toks0): not all of the scratch items have sensible names :-)
    – Joseph Wright
    Dec 26, 2012 at 21:31
  • 5
    I disagree about \if@tempswa; it's not "reserved to the team".
    – egreg
    Dec 26, 2012 at 21:31
  • @egreg: Sure, but doesn't it deal with \labels and using it for other things could influence the behaviour?
    – Werner
    Dec 26, 2012 at 21:34
  • 1
    @JosephWright: What about \skip@, \dimen@, \dimen@i and \dimen@ii? Would these also be considered temporary?
    – Werner
    Dec 26, 2012 at 21:37
  • 2
    @Werner The kernel never assumes some value of \if@tempswa and when the conditional is used, it's always initialized at the start. When using a "scratch" register (or boolean) one should ensure that this usage will not clobber the same registers. In case of doubt a new register or conditional must be allocated.
    – egreg
    Dec 26, 2012 at 21:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .