什么时候适合使用 \outer?

什么时候适合使用 \outer?

\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声明的内容:\outerplain

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 的良好用法。因此,您的问题的答案是“几乎没有”。

相关内容