似乎这个原语是为了防止程序员忘记}
在宏定义的末尾添加(在这种情况下,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
)。
用法
[由于与旧链接问题重叠过多,因此删除该部分。]