我有疑问
\infer{$\forall x\in A. P(x)$}{$\forall x\in A.(\forall y\in A.x\xrightarrow{+}y\implies P(y))\implies P(x)$}
我看过这回答但找不到帮助
答案1
回答:
在这种情况下,
\infer
(从proof
包 (package) 要求其参数为公式,因此其参数已用美元符号包围。您应该删除所添加的多余符号。一般提示:始终将“缺少 $ 插入”解释为“TeX 在非数学模式下遇到了以下数学模式问题”,并首先尝试找出为什么TeX 未处于数学模式。(有时实际上是缺少美元符号,但在这种情况下,这是因为它刚刚退出数学模式,因为有“多余”的美元符号。)
关于 TeX 错误消息和调试的更多详细答案:
尽管错误消息乍一看很奇怪,但原则上从错误输出来看一切都是有意义的,特别是如果您添加\tracingall
并知道要查找什么。
\documentclass{article}
\usepackage{amsmath}
\usepackage{proof}
\begin{document}
\tracingall
\infer{$\forall x\in A. P(x)$}{$\forall x\in A.(\forall y\in A.x\xrightarrow{+}y\implies P(y))\implies P(x)$}
上面的输入中,您\infer
在括号中输入了两个内容:第一个是
{$\forall x\in A. P(x)$}
第二个是
{$\forall x\in A.(\forall y\in A.x\xrightarrow{+}y\implies P(y))\implies P(x)$}
输出\tracingall
显示\infer
,经过足够多的步骤后,TeX 会尝试扩展一个内部命令,\@infer [#1]#2#3
其中
#1<-\@empty
#2<-$\forall x\in A. P(x)$
#3<-$\forall x\in A.(\forall y\in A.x\xrightarrow {+}y\implies P(y))\implies P(x)$
这比最终的错误信息稍微高一点,即:
! Missing $ inserted.
<inserted text>
$
<to be read again>
\forall
<argument> $\forall
x\in A. P(x)$
\@infer [#1]#2#3->\relax \if@ReturnLeftOffset \else \@SavedLeftOffset =\@LeftOffset \fi \setbox \@LabelPart =\hbox {$#1$}\relax \setbox \@LowerPart =\hbox {$#2
$}\relax \global \@LeftOffset =0pt \setbox \@UpperPart =\vbox {\tabskip =0pt \halign {\relax...
l.7 \infer{$\forall x\in A. P(x)$}{$\forall x\in A.(\forall y\in A.x\xrightarrow{+}y\implies P(y))\implies P(x)$}
?
这表明 this 的定义\@infer
是:
\@infer [#1]#2#3->\relax \if@ReturnLeftOffset \else \@SavedLeftOffset =\@LeftOffset \fi \setbox \@LabelPart =\hbox {$#1$}\relax \setbox \@LowerPart =\hbox {$#2
$}\relax \global \@LeftOffset =0pt \setbox \@UpperPart =\vbox {\tabskip =0pt \halign {\relax...
(...
上面最后一行末尾的 表示定义尚未完成!)其中,在执行命令\hbox {$#2$}
(#2
遇到时将被替换)时,会发生什么:
首先,TeX 发现
\hbox
并进入受限水平模式。然后它看到
$
(来自的定义\@infer
)并进入数学模式(并做一些事情,比如更改字体系列和执行中的任何内容\everymath
)。然后它看到
#2
并替换其定义$\forall x\in A. P(x)$
。因此当它看到第一个字符时
$
,它离开数学模式。然后它看到
\forall
,此时有了定义\mathchar"238
。这个
\forall
(\mathchar"238
)只能在数学模式下使用,因此 TeX 会$
在读取它(进入数学模式)之前“有帮助地”插入一个符号,但只是暂时的:它还会“有帮助地”让你知道(在继续对$
插入的符号采取行动之前)它将要做什么,以防你想改变将要发生的事情。
这解释了错误消息,该消息由一条消息和后跟表示输入堆栈的几行组成:
! Missing $ inserted.
^ 錯誤信息。
<inserted text>
$
^ 输入堆栈的第一级:TeX 即将读取$
它插入的内容,并通知您。
<to be read again>
\forall
^ 输入堆栈的第二级:\forall
TeX 先前读取过并放回了(当它遇到错误时),接下来它将再次读取它(如果您允许的话)。
<argument> $\forall
x\in A. P(x)$
^ 输入堆栈的第三级:在读取一个参数$\forall x\in A. P(x)$
(这是一个宏的参数,将在下文中展示)时,TeX 已完成读取$\forall
,但尚未读取x\in A. P(x)$
。
\@infer [#1]#2#3->\relax \if@ReturnLeftOffset \else \@SavedLeftOffset =\@LeftOffset \fi \setbox \@LabelPart =\hbox {$#1$}\relax \setbox \@LowerPart =\hbox {$#2
$}\relax \global \@LeftOffset =0pt \setbox \@UpperPart =\vbox {\tabskip =0pt \halign {\relax...
^ 输入堆栈的第四级:TeX 在遇到参数时正在扩展的宏。请注意,在这里您可以看到它刚刚读取\hbox{$#2
,这就是正在发生的事情的线索。
l.7 \infer{$\forall x\in A. P(x)$}{$\forall x\in A.(\forall y\in A.x\xrightarrow{+}y\implies P(y))\implies P(x)$}
^ 输入堆栈的第五级:TeX 读取的源文件的第 7 行。
?
^ 提示,询问您如何继续。如果您按 Enter,它将读取$
然后(从堆栈的前三层开始),然后继续读取从开始的堆栈的第四层\forall
(这将导致另一个错误)。x\in A. P(x)$
$
顺便说一句,推测什么样的设计或用户惯例可以避免这种无用的(至少乍一看)错误消息,从而获得更愉快的用户体验,这很有趣(作为一种无聊的想象力练习)。我轻率的回答是不要使用太多宏。:) 但更严肃地说,也许某种方式让包指定宏的某个参数是否应该是公式,并首先检查这一点(在输入到 TeX 内部之前)会有所帮助。不确定 expl3 是否提供了这个。另一件可能有帮助的事情是某种形式的 TeX 正在做什么的交互式/慢动作显示(比\tracingall
这更好的东西需要一些经验才能理解),这样你就可以看到 TeX 因为 而进入了数学模式\infer
,并且因为您的 而离开了数学模式$
,在遇到 之前\forall
。
答案2
正如@Schrödinger's cat 在评论中指出的那样,解决方法是不要$..$
在已经在里面时使用\infer
,因为它会切换到数学模式