6

It seems that this primitive was designed for the purpose that in case programmers forgot to put } in the end of the definition of a macro (in this case, TeX thought all characters until the end of the current file is a part of the definition of this macro). I cannot grasp the idea behind this macro, especially that sentence

When a macro definition is preceded by \outer, the corresponding control sequence will not be allowed to appear in any place where tokens are being absorbed at high speed.

How to use \outer and what's the meaning of high speed by DEK?

7
  • 5
    it has no justification at all:-), must be the worst part of the TeX design. LaTeX doesn't use it, luatex has a setting to disable it completely. It's an error-detecting feature that has generated orders of magnitude more errors than it ever deteced. May 16 at 7:24
  • Well, most people here use LaTeX, but if you use TeX the exact way Knuth used it you would likely find it useful...
    – user202729
    May 16 at 7:54
  • Actually the "how to use" part is already covered in macros - When is it appropriate to use \outer? - TeX - LaTeX Stack Exchange . I don't think there's one that ask for exact semantic though (because... people can generally figure it out by testing?)
    – user202729
    May 16 at 8:07
  • @user202729 I also use LaTeX, I am jusst curious about how the underlying engine works. For me, TeX is a programming language, its engine is a compiler. this language is harder than C++ :)
    – Lucas
    May 16 at 8:33
  • 1
    @user202729 I don't think latex or plain makes much difference here, it's not useful in plain TeX either May 16 at 14:18

3 Answers 3

9

Don't use \outer it never does anything useful (despite the fact that I use it in the bm package:-)

"High speed" here means when TeX is tokenizing input without evaluating it. So for example in plain TeX

\def\foo{...\newcount\abc  \abc=42 ...}

You get an error as the replacement text of \foo is being collected, as \newcount is outer in plain.

lots of macros reasonably want to embed \newcount. eg a \newthorem construct probably needs to allocate a theorem counter. The plain TeX version has to use contortions like \csname newcount\endcsname just to avoid the outer \newcount token, which is outer just to discourage use of \newcount in a macro that is used often, in a way that would allocate a counter on each use, and run out of count registers.

3
  • 1
    Preventing unbounded absorption of tokens by placing an \outer token (like in bm) is a reasonable use-case I'd say. May 16 at 8:33
  • 2
    @HenriMenke yes sure, what I meant is "it never does anything useful, unless you are me:-) or more seriously never on a user callable command. The bm case is a command that should never appear at all so outer is a cheap way to catch it, May 16 at 9:30
  • 1
    If I understand the TeXbook correctly, this was in some way also the original intention of user-facing \outer macros. With 1980s computing power you didn't want to wait for 20 minutes until TeX had reached the end of the document to tell you that you're missing a }. May 16 at 9:36
5

How to use \outer? Keep at arm's length from it: it bites.

Suppose you want to exploit \proclaim but you also want to automatically number your statements. You do

\newcount\statementcounter
\def\statement#1{%
  \global\advance\statementcounter by 1
  \proclaim#1 \number\statementcounter. \ignorespaces
}

\statement{Definition} This is the definition of foo.

\statement{Theorem} This is the statement of a theorem about foo.

Now text follows.

\bye

It ought to work, you say. Well, no: you get a very bizarre error message

Runaway definition?
#1->\global \advance \statementcounter by 1
! Forbidden control sequence found while scanning definition of \statement.
<inserted text>
                }
<to be read again>
                   \proclaim
l.5   \proclaim
               #1 \number\statementcounter. \ignorespaces
?

OK, how to do it? Simple:

\newcount\statementcounter
\def\statement#1{%
  \global\advance\statementcounter by 1
  \csname proclaim\endcsname#1 \number\statementcounter. \ignorespaces
}

\statement{Definition} This is the definition of foo.

\statement{Theorem} This is the statement of a theorem about foo.

Now text follows.

\bye

Apparently, Knuth doesn't use automatic numbering and is pleased to do it by hand (or he's able to type in papers directly without ever changing his mind about the order of statements).

Well, this was not what I was actually trying to do: I wanted to do automatic numbering using the AMS-TeX version of \proclaim that suffers from the same problem (I was typesetting the book written by my “Maestro”, whom I owe so much).

In plain.tex you also find

\def\tabalign{\us@true\m@ketabbox} % non-\outer version of \+
\outer\def\+{\tabalign}

which seems to mean that Knuth himself got bitten by \outer.

What does “high speed” mean? Basically, it means “macro expansion is suppressed”, see When does tex do macro expansion?

Indeed, you can try

\newcount\statementcounter

\edef\statement#1{%
  \global\advance\statementcounter by 1
  \noexpand\proclaim#1 \noexpand\number\statementcounter. \ignorespaces
}

\statement{Definition} This is the definition of foo.

\statement{Theorem} This is the statement of a theorem about foo.

Now text follows.

\bye

and you'll see no error about \outer, because \proclaim is seen when TeX is doing macro expansion.

If you want to “de\outerize” \proclaim, you can do

\newcount\statementcounter

\let\OUTERPROCLAIM\proclaim
\edef\proclaim{\noexpand\OUTERPROCLAIM}

\def\statement#1{%
  \global\advance\statementcounter by 1
  \proclaim#1 \number\statementcounter. \ignorespaces
}

\statement{Definition} This is the definition of foo.

\statement{Theorem} This is the statement of a theorem about foo.

Now text follows.

\bye

There are other methods; this doesn't rely on knowing the actual definition of the \outer macro.

3
  • Your example inspired me to implement another macro.
    – Lucas
    May 16 at 14:30
  • I think it mean "sometimes he need to use \+ within another macro and is okay with selecting either of them depends on the need" instead. It does serve the "error checking" part if you do that
    – user202729
    May 16 at 14:34
  • 1
    @user202729 After having used plain TeX or AMS-TeX for several years, I still don't understand what \outer should do, besides hindering programmers. Well, I see nothing too strange in declaring \bye to be outer, even though I can imagine applications where \bye is in the replacement text of a macro. For \+ or \proclaim there is no reason. And, indeed, Spivak removed all \outer commands in his LAMS-TeX extension of AMS-TeX.
    – egreg
    May 16 at 15:29
2

Meaning of "high speed"

Reading the book carefully helps.

In this case, it's explained right in the next sentence.

An \outer macro cannot appear in an argument (not even when \par is allowed), nor can it appear in the parameter text or the replacement text of a definition, nor in the preamble to an alignment, nor in conditional text that is being skipped over.

Look up \halign for what "alignment preamble" means. "conditional text that is being skipped over" means e.g. if \verb were outer, then \iffalse \verb|\fi| \fi would be invalid (side note, the actual implementation stops at the first \fi).

Usage

[section removed because of too much overlap with the old linked question.]

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.