我正在尝试编写一个递归,使用\aftergroup
它在每个组末尾执行某些操作。mwe:
\protected\def\printB{B \aftergroup\printB}
$$\halign \bgroup ${#}$\cr a \printB \crcr\egroup$$
\bye
eTex 因错误而中断! Missing $ inserted.
某些情况是如何发生的,它不仅\aftergroup
需要宏。 是否可以保护这样的扩展?$
\printB
答案1
\aftergroup
只需要一个标记\printB
,但递归永远不会结束,如果你添加一个\message
\protected\def\printB{\message{.}B \aftergroup\printB}
$$\halign \bgroup ${#}$\cr a \printB \crcr\egroup$$
\bye
你看
. . . . . .
! Missing $ inserted.
<inserted text>
$
<to be read again>
\par
\bye ->\par
在失败之前它被调用了 6 次。
$
最终导致错误的额外原因是因为 aftergroup-inserted 标记是在之后插入的\crcr
,因此会启动一个新的 halign 行,因此{#}
模板已被插入,但您永远不会结束该行,直到最终遇到\bye
错误。
您会看到基本上相同的错误,但有\aftergroup
一个明确的B
\crcr
\halign {
${#}$\cr a \crcr B}$$
\bye
生产
! Missing $ inserted.
<inserted text>
$
<to be read again>
\par
\bye ->\par
\vfill \supereject \end
l.4 \bye
? x
答案2
请考虑以下示例:
\tabskip=30pt
\halign{{$#$x}&u#v\cr
a\aftergroup b&c\cr
a\aftergroup \aftergroup \aftergroup b&c\cr
a\aftergroup \aftergroup \aftergroup \aftergroup
\aftergroup \aftergroup \aftergroup b&c\cr
}
\bye
在第一种情况下,b
打印在数学模式之外。在第二种情况下,它打印在 周围的组之后$#$x
。在第三种情况下,它打印在\halign
单元格周围的隐式组之后,因此最终成为下一个单元格中的第一个项目。
你定义\printb
要做的事情b\aftergroup\printb
是希望当 TeX 到达顶层时\aftergroup
不会产生任何影响,但是……
就像第三个案例b
中打印的那样第二对齐的单元格,在你的情况下,b
当 TeX 尚未看到}
结尾时,将出现\halign
。由于b
不是\omit
,因此会开始一个新单元格,形成一个组……
一个更简单的例子是
\def\printb{b\printb}
\halign{#\cr a\printb\cr}
\bye
问题完全一样。
如果你认为这\crcr
结束了,\halign
那你可真错了。它的功能是执行\cr
(原始的\cr
),前提是它不遵循一个(原始的)\cr
命令。在那个位置上,它与 相同\cr
。