\frac 误差的有趣递归行为

\frac 误差的有趣递归行为

我有以下代码。显然,这实际上不是有效的代码,因为没有第二个参数\frac,但尽管如此,我还是很好奇它为什么会产生这样的结果。

\[
  \text{abc$\frac{123}$}
\]

在此处输入图片描述

如果您在命令中使用内联或显示数学模式,则您只能看到递归行为(获取重复的、较小的 abc-123)\text{}。更改所使用的数学模式会稍微改变结果,但重复的 abc-123 仍然存在。

如果不包含该\text{}命令,则会得到“预期”的输出,例如

abc$\frac{123}$ 两者 \[ abc\frac{123} \] 都为您提供单个 abc-123

在此处输入图片描述

有人知道什么内部运作导致了递归行为吗?

梅威瑟:

\documentclass{article}

\usepackage{amsmath}


\begin{document}

\[
    \text{abc$\frac{123}$}
\]

\[
    abc\frac{123}
\]

abc$\frac{123}$

\[
    \text{abc\[\frac{123}\]}
\]

\end{document}

答案1

为了理解发生了什么,让我们考虑一个稍微简单一点的例子。定义\macro为一个带有一个参数的宏

\newcommand\macro[1]{abc}

参数被忽略,扩展仅包含abc。现在我们使用\macro\text省略参数。

\[ \text{$\macro$} \]

结果与您观察到的类似:

在此处输入图片描述

为了进一步理解这一点,让我们写出一些类似于\text底层的东西(当然是彻底简化的)。输出与 相同\text

\[ \mathchoice{\hbox{$\displaystyle \macro$}}%
              {\hbox{$\textstyle \macro$}}%
              {\hbox{$\scriptstyle \macro$}}%
              {\hbox{$\scriptscriptstyle \macro$}} \]

这里我们使用了 ,\mathchoice这是一个原语,它接受四个参数,每个参数代表一种可能的数学样式,由我在 中使用的样式宏指示\hbox。每个参数都在一个临时框中展开和排版,但只会输出与当前样式相对应的参数。因此,以下代码片段将导致

\[ \mathchoice{D}{T}{S}{SS} \] % -> D
$ \mathchoice{D}{T}{S}{SS} $ % -> T
$ _{\mathchoice{D}{T}{S}{SS}} $ % -> S
$ _{_{\mathchoice{D}{T}{S}{SS}}} $ % -> SS

这是使其正确适应周围数学风格的机制\text。现在,在我们的缺失参数示例中会发生什么。如果我们展开,\macro我们得到

\[ \mathchoice{\hbox{$\displaystyle abc}}%
              {\hbox{$\textstyle abc}}%
              {\hbox{$\scriptstyle abc}}%
              {\hbox{$\scriptscriptstyle abc}} \]

哎呀,\macro吃掉了结尾$,现在有很多不匹配的$。现在我们可以通过阅读错误消息来跟踪 TeX 的扫描过程。第一个错误是

! Extra }, or forgotten $.
l.4 \[ \mathchoice{\hbox{$\displaystyle \macro$}
                                               }%

TeX 告诉我们,错误发生在读取}之后\macro$,换行符表示。它还告诉我们,它原本期待的是$,但却遇到了}。这很合理,因为\macro刚刚吞下了$。以下几行也发生了完全相同的情况,TeX 仍在寻找$永远不会出现的结束符,因此所有内容都记录在 的第一个参数中\mathchoice。这甚至超出了数学环境的范围,并且只有在$平衡或到达文档末尾时才会结束。最终,TeX 意识到事情出了问题,并开始插入多个$和 ,}直到满足条件为止。然后,它排版 的第一个参数,\mathchoice其中包含直到无效部分为止的所有内容。你可以用这个制作有趣的东西

\documentclass{article}
\usepackage{xcolor}
\newcommand\macro[1]{abc}
\begin{document}

$ \mathchoice{unused}%
             {\hbox{\color{red}$\textstyle \macro$}}%
             {scriptstyle}%
             {scriptscriptstyle} $
Wait, what is happing?
Why is everything red and in one line?
What happened to the linebreaks?
When is this ever going to end?

\end{document}

这种\frac情况有点难以解释,因为它里面有一个组,但大致的工作原理是一样的。未终止的宏会吃掉尾随的字符$,而 TeX 会继续扫描,直到$达到平衡或到达文档末尾。

答案2

前提是错误的。代码中的第二个参数\frac正是$

的定义frac

\DeclareRobustCommand{\frac}[2]{{\begingroup#1\endgroup\@@over#2}}

其中与重新定义以产生警告的原语相同。由于该命令需要两个参数,因此它可以作为第一个参数进行扫描,\@@over然后由于没有后续参数,它会吸收下一个参数\overamsmath{123}{令牌作为第二个参数。因此,您得到的结果是

$\frac{123}{$}

现在这变成了

${\begingroup123\endgroup\@@over$}

这已经会产生

! Missing } inserted.
<inserted text>
                }
l.6 $\frac{123}$

?
! Too many }'s.
\frac  #1#2->{\begingroup #1\endgroup \@@over #2}

l.6 $\frac{123}$

?

即使不在 内\text$由于 尚未平衡,因此该标记出现在它不应该出现的位置,{因此 TeX 添加}以进行恢复;然后它重新扫描$,这将结束数学模式,并且下一个}会触发错误,因为它不再与相应的 平衡{

情况\text更糟,因为\text会产生四个版本的参数,以便根据最终的数学风格只使用其中一个。上面的两个错误将变成错误消息,但略有不同,因为它们是在 TeX 正在处理时生成的\text\text@是其内部版本,仅供参考):

! Missing } inserted.
<inserted text>
                }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Missing { inserted.
<to be read again>
                   }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Missing } inserted.
<inserted text>
                }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Missing { inserted.
<to be read again>
                   }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Missing } inserted.
<inserted text>
                }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Missing } inserted.
<inserted text>
                }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Extra }, or forgotten $.
\text@ ...style \ssf@size {\firstchoice@false #1}}
                                                  \check@mathfonts }
l.6 \[\text{$\frac{123}$}
                         \]
?
! Extra }, or forgotten $.
\text@ ...firstchoice@false #1}}\check@mathfonts }

l.6 \[\text{$\frac{123}$}
                         \]
?

“abc” 后面跟着一个无分母分数的三个变体,这只是错误恢复的副产品,不应该“认真对待”。实际上,按回车键八次就能让 TeX 同步,这相当令人惊讶。

相关内容