让狮子跑来跑去。简洁地

让狮子跑来跑去。简洁地

各种构造都可能导致 TeX(又名狮子)陷入无限循环。最简单的例子是\def~{~}~,它定义~为扩展为自身,然后扩展它。现在,如果我们排除宏扩展,获得循环就更加困难了。对于纯 TeX,我发现的两种最短方法(不使用宏)是

\everypar{\the\everypar}.
\toksdef~0~{\the~}\the~.

\the\toks0(包括尾随的点);请注意,第二个不是宏扩展,而是隐藏的扩展。使用 eTeX,我

\if\unexpanded\fi

它具有可扩展的额外“特性”。这里,\unexpanded可以替换为\detokenize\scantokens

  1. 为什么这会引发无限循环?
  2. 是否存在类似的短 TeX 构造,并且不使用宏扩展(最好仅使用原语)?

答案1

我认为已经理解了为什么会触发无限循环。e-TeX 基元\unexpanded大致如下\lowercase:它后面应该跟着<general text>,而后者又是<filler>{<balanced text><right brace>。重要的是<filler>,它是命令和空格的任意序列\relax(TeXbook,第 276 页)。

所以\unexpanded寻找{随时扩展的命令并忽略\relax空格标记。但它是可扩展的!

当 e-TeX 找到 时\if\unexpanded\fi,原语\if会触发 的扩展\unexpanded;但是\fi紧随其后的 会导致插入一个 (frozen) \relax,因为未完成的条件会\unexpanded被吞噬,留下一个未完成的条件,从而导致插入\relax

哎呀,无限循环。对于\detokenize和的\scantokens情况是一样的。在原始的 TeX 中<general text>据我所知,可扩展原语接受一个as 参数。

情况确实完全不同\if\lowercase\fi\lowercase其中不是可扩展,因此 TeX\relax可以插入并进行比较(并且是正确的)。

答案2

不是特别短,但是我在开发过程中遇到了一个真正的错误xor

\output{\deadcycles=1
        \message{.}%            just to show that something is happening
        \setbox0\box255}
\null
\bye

当然,输出例程没有设置\deadcycles为 1。实际上,它是连续调用两个 OR,第一个将其设置为零。

刚刚意识到我只回答了问题的第二部分。到目前为止,第一部分已经由@egreg 回答了。

答案3

仅使用经典 tex 且不使用宏扩展的较短循环是

\let\par\relax.\vskip

或者

\let

\noindent

\vskip

相关内容