\outer
是一个奇怪的野兽。任何声明的控制序列\outer
都不能用作宏的参数文本或替换文本,至少在控制序列是\outer
在参数被标记或定义被扫描时声明的情况下是这样。也就是说,的定义\bar
和使用\baz
都是错误的:
\outer\def\foo{asdf}
\def\bar{\foo}
\def\baz#1{#1}
\baz\foo
但是,稍微改变一下,
\def\bar{\foo}
\def\baz#1{\outer\def\foo{asdf}#1}
\baz\foo
\bar
因此,只有在定义之后并且参数被解析之后\foo
才声明,才能正确编译。\outer
\bar
\baz
我可以看到要求宏只出现在垂直模式下,但\outer
事实并非如此。事实上,\outer
控制序列可以出现在垂直、内部垂直、水平、限制水平、数学和显示数学模式中的任何一种模式下。
\outer\def\foo{asdf}
\foo% vertical mode
foo \foo% horizontal mode
\hbox{\foo}% restricted horizontal mode
\vbox{\foo}% internal vertical mode
$\foo$% math mode
$$\foo$$% display math mode
\bye
那么考虑到所有这些,的用处是什么\outer
?
答案1
\outer
在 LaTeX2e 中没有使用,我也不知道有任何软件包使用(但可能有一些)。不过,我偶尔会觉得这可能是一个好主意。
\outer
防止宏在任何其他宏内使用。但什么时候这是可取的?好吧,考虑使用\verb
: ,因为它会更改 catcode,而 catcode 在标记化发生时会被冻结,因此\verb
永远不能(可靠地)在任何其他宏内使用。例如,这将不起作用:
\section{The \verb|\outer| primitive}
现在,\verb
无论如何,包含自己的处理以在这种情况下给出合适的错误消息,但还有其他软件包定义了使用 catcode-mucking 来完成工作的命令。例如,\url
如果在宏中使用某些索引命令和,例如,,则会产生错误的输出。理论上,您可以使用\outer
来强制仅在运行文本中使用它们,但这种情况并不常见。
还要注意的是,eTeX 提供了\scantokens
许多在标记化发生之前只能更改 catcode 的限制。因此\outer
从这个角度来看,现在用处不大了。
答案2
根据 TeXbook, 的唯一和预期目的是\outer
检测\long
宏的失控参数和其他禁止\par
对您无济于事的情况(第 206 页)。 Knuth 明确指出,他希望格式作者对其宏做出明智的选择,以便文档结构可以告知 TeX 是否存在缺失的右括号。 要了解他认为哪种选择具有歧视性,以下是他在样式(附录 B)和 TeXbook 格式(附录 E)中\outer
声明的内容:\outer
plain
在plain
:
\new
任何事物(计数、尺寸等)^^L
,正如 Lev Bishop 所指出的\+
(制表符跳过命令)\proclaim
(作为定理环境),\beginsection
\bye
(本文结束)
在 TeXbook 中:
\beginchapter
,,,,,,,,,(它们基本上都是分段命令\endchapter
)\begindisplay
\enddisplay
\begintt
\exercise
\dangerexercise
\ddangerexercise
\answer
\danger
,\ddanger
(用于放置布尔巴基“危险弯道”标志)
Will Robertson 说 LaTeX2e 不使用\outer
,因此那里没有课程,但基于这个例子,我想说,如果它是由 Knuth 编写的,那么诸如\section
和之类的宏\chapter
,以及一般可能的环境,都将是\outer
。
那么,概括来说,我认为\outer
应该使用 来将文档结构的意图从作者传达给 TeX:指示文档的哪些区域是自包含的。当然,按照设计,它完全是为了保护作者免受他们自己的干扰(它仅用于错误检查,而不是用于布局),因此考虑到它的预期位置是在高级结构宏中,一般 TeX 用户似乎不太可能使用他们自己定义的任何宏\outer
:有多少人为自己使用而编写格式,或者就此而言,有多少人编写格式?
TeX 的一些设计决策中还出现了另一个问题\outer
,它与时间的流逝有关。也就是说,这个宏似乎是为了最大限度地减少重复劳动而设计的,因为它有助于提供有用的诊断。我使用 LaTeX 的经验是它不提供有用的诊断:每当我遇到错误时,我通常会得到几十个错误,而且只有第一个错误有意义。我纠正了那个错误,然后重新编译;通常这可以消除所有后续错误。
谨慎使用\outer
可以将无意义的错误限制在文档的小区域内,这样一旦跨越了分段边界,就不会再因任何一个宏中的括号不平衡而产生错误。因此,希望调试过程可以在错误数量的亚线性时间内进行(或者至少以较小的系数线性进行)。我认为很少有年轻的计算机用户(像我一样)习惯于对他们的工作进行批处理,这在共享计算、付费计算机时间和较慢处理器的时代可能更为必要。无论好坏,我们现在可以与我们的机器进行(有时是敌对的)对话。
答案3
我认为这两种方法都没有实际用处\outer
,因为除了在简单情况下,它们的语义不会产生任何帮助。在实际情况下(例如在更复杂环境的设置宏中),即使改变类别代码的宏在参数中也可以完全有意义。
旧版本的 LuaTeX 会默认忽略\outer
。后来应要求进行了更改,以便与旧引擎更兼容,因此现在\outer
可能会再次产生错误,但仍可以通过指定以下代码禁用此向后兼容功能:
\suppressoutererror=1
在源代码中。
答案4
Latex 将 ASCII 换页^^L
符定义为\outer
。这是我能想到的唯一一个 outer 的良好用法。因此,您的问题的答案是“几乎没有”。