\outer 原语背后的想法

\outer 原语背后的想法

似乎这个原语是为了防止程序员忘记}在宏定义的末尾添加(在这种情况下,TeX 认为直到当前文件末尾的所有字符都是这个宏定义的一部分)。我无法理解这个宏背后的想法,尤其是那句话

当宏定义前面带有 时\outer,相应的控制序列将不允许出现在任何正在高速吸收令牌的地方。

DEK如何使用\outer以及含义是什么?high speed

答案1

不要使用\outer它永远不会做任何有用的事情(尽管我在bm包中使用它:-)

这里的“高速”是指 TeX 在没有评估输入的情况下对输入进行标记。例如在纯 TeX 中

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

\foo在收集替换文本时,您会收到错误消息,因为\newcount文本外部就是纯文本。

许多宏都合理地想要嵌入\newcount。例如,\newthorem构造可能需要分配一个定理计数器。普通的 TeX 版本必须使用类似于的扭曲\csname newcount\endcsname来避免外部\newcount标记,外部标记只是为了阻止在经常使用的宏中使用\newcount,每次使用时都会分配一个计数器,并且用尽计数寄存器。

答案2

如何使用\outer?远离它:它会咬人。

假设你想利用,\proclaim但你也想自动对语句进行编号。你

\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

你说,这应该能用。但事实并非如此:你收到了一条非常奇怪的错误消息

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
?

好的,怎么做呢?很简单:

\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

显然,Knuth 不使用自动编号,而是乐于手工编号(或者他可以直接在论文中输入,而无需改变语句的顺序)。

好吧,这不是我真正想要做的:我想使用\proclaim存在同样问题的 AMS-TeX 版本进行自动编号(我正在排版我“大师”写的书,我欠他太多了)。

plain.tex还会发现

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

这似乎意味着 Knuth 本人也被咬了\outer

“高速”是什么意思?基本上,这意味着“宏扩展被抑制”,见tex 什么时候进行宏扩展?

事实上你可以尝试

\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

并且您将看不到有关的错误\outer,因为\proclaim当 TeX进行宏扩展。

如果你想“定制\outer\proclaim,你可以这样做

\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

还有其他方法;这并不依赖于了解\outer宏的实际定义。

答案3

“高速”的含义

读书小心有帮助。

在这种情况下,下一句话就解释了一切。

\outer不能出现在参数中(即使\par允许也不行),也不能出现在参数文本或定义的替换文本中,也不能出现在对齐的前言中,也不能出现在被跳过的条件文本中。

查找\halign“对齐前言”的含义。“被跳过的条件文本”意味着例如如果\verb在外面,那么\iffalse \verb|\fi| \fi将是无效的(旁注,实际的实现在第一个停止\fi

用法

[由于与旧链接问题重叠过多,因此删除该部分。]

相关内容