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.

I'm a user primarily of Plain TeX. Lately I get annoyed about the \outer nature of \newcount, especially when I write macros which require temporary internal variables, variables which really need not be global. I'm aware that I can technically use \count0 through \count9 as scratch variables, but I got scared away from doing so when The TeXbook mentioned that those are also used as page counters, and how using them when a page shipout gets triggered can mess up page numbering.

So, my question is this: why is \newcount declared \outer? I've check that names created with \countdef can indeed be locally scoped within groups, and I know that changes to \count registers are likewise locally scoped. So why was it that Knuth chose to tag \newcount with the \outer restriction? And would there be anything preventing me from defining my own \countdef-based allocator, specifically one that would allow for group-local names.

share|improve this question
    
Probably only DEK can answer 'why': we can at best manage 'what effects ...' :-) –  Joseph Wright Apr 28 at 6:30
    
Because TeX is a bad programming language and doesn't have concepts like variables or scoped functions. You have to leave your expectations from other languages' best practices at the door. –  Ryan Reich Apr 28 at 17:12

2 Answers 2

up vote 10 down vote accepted

At a technical level, making a macro \outer doesn't add anything: it's purely a restriction (much the same as \def is a subset of \long\def). Thus the reasoning here is about ensuring the input follows a particular pattern.

Register allocation is done much the same in plain, LaTeX and ConTeXt (at least fundamentally), with the exception that only plain does it with \outer macros. Thus there is not a 'limitation' in a technical sense in having 'normal' macros here. The one thing making them \outer does prevent is something like

\def\foo#1{%
  \newcount\mycount
   ...
}

which you occasionally see as a misunderstanding of the scope of TeX assignments. (I'm assuming here \foo is used many times in a document.)

Of course, you can still use \outer macros inside other macros using \csname:

\def\foo#1{%
  \csname newcount\endcsname\mycount
 ...

Note that the LaTeX etex package and 'e-plain' formats both include code to allow 'local register assignment': the etex package code contains very little LaTeX, so perhaps take a look at \loccount in that (e.g. less `kpsewhich etex.sty` on *nix).

share|improve this answer
3  
making \newcount be \outer did have a positive effect in the early days of tex -- it kept one from running out of memory (\hashcode, if i remember correctly) when a counter was defined locally in a frequently used command. local definition causes another instance of the command name to be defined internally, and that resource was very much smaller than it is nowadays. without that protection, errors were much more common using latex than with plain tex for people who didn't pay attention to the need to write clean code. (and with slower machines, ...) –  barbara beeton Apr 28 at 8:51
    
@barbarabeeton That issue was what I was trying to point to with my \foo example. Fundamentally it's not being solved by the token being \outer but by it enforcing 'best practice'. –  Joseph Wright Apr 28 at 9:07
3  
"best practice" has always been desirable, of course, but when it took maybe five minutes to compile one page, every "incentive" was helpful. my guess is that knuth applied that restriction as an aid to himself. –  barbara beeton Apr 28 at 9:17

Counters are precious, because there are only 256 of them and several are already allocated or used by TeX: the first ten are reserved for page counters, as required by the DVI format; counters from 10 to 21 are used for bookkeeping related to register allocations and \count255 is kept as a scratch register. The Plain format reserves other six (two implicitly via \newinsert).
Note: here I'm taking the point of view of Plain TeX run with the original program without e-TeX extensions.

While the number of available counters seems still large, one has to keep in mind that a \newcount instruction does global assignments. Let's see:

\outer\def\newcount{\alloc@0\count\countdef\insc@unt}
\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne
  \ch@ck#1#4#2% make sure there's still room
  \allocationnumber=\count1#1%
  \global#3#5=\allocationnumber
  \wlog{\string#5=\string#2\the\allocationnumber}}

Thus \newcount\foo does

\global\advance\count10 by 1
\ch@ck0\ins@count\count
\allocationnumber=\count10
\global\countdef\foo=\allocationnumber
\wlog{\string\foo=\string\count\the\allocationnumber}

Some lines above we find

\count10=22 % allocates \count registers 23, 24, ...

so we know that \count10 stores the last allocated count register's number. The first available in user space would be number 23, but Plain TeX has three \newcount instructions. Thus \newcount\foo would print

\foo=\count26

in the log file.

Now you see that register's allocation is sequential. There's no way for “unallocating” a register without drastically changing the macros using a pool rather than a sequential strategy.

A macro definition such as

\def\amacro#1{\newcount\temp \temp=#1\relax ...}

would globally waste a register each time it's called: trust me, I've seen several instances of this error in LaTeX macros; as you know \newcounter and \newcount are not \outer in LaTeX. Sometimes it's \newlength, but the idea is the same.

By declaring \newcount and the other similar allocation macros as \outer, this kind of error is (almost) impossible to make.
Note that this would be an error also with the 32768 registers allowed by e-TeX or the 65536 made available by LuaTeX. The registers would only be exhausted later.

There are cases where \newcount would be legal in a macro: if we want to define an interface, say for introducing hierarchical sectional commands, we have to allow \newcount\subsectioncount as part of the (fictional) command

\definelevel{subsection}{...}

But here it's not “user space”: the definition of \definelevel is made by a programmer, who knows (or, at least, should know) what's being done. A programmer would type

\csname newcount\expandafter\endcsname\csname#1 count\endcsname

in the code for \definelevel, overriding the outerness of \newcount.

share|improve this answer
    
'Counters are precious': well, since 1990 there have been 64k available! (OK, e-TeX allocates the first 256 in such a way as they are more efficient than the 'extended pool', and you have to take those for \inserts from the 'basic' set.) –  Joseph Wright Apr 28 at 9:10
    
@JosephWright I was taking Knuth's point of view. –  egreg Apr 28 at 9:14
    
Yes, I can see that: just wanted to note that the restriction is altered in newer engines. –  Joseph Wright Apr 28 at 9:16

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.