这不能编译,这正是我所期望的:
\documentclass{amsart}
\newcommand{\G2}{G_2}
%\DeclareMathOperator{\G2}{G_2}
\begin{document}
\(\G2\)
\end{document}
生产
! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.2 \newcommand{\G2}{G_2}
?
这确实可以编译,但这不是我所期望的:
\documentclass{amsart}
%\newcommand{\G2}{G_2}
\DeclareMathOperator{\G2}{G_2}
\begin{document}
\(\G2\)
\end{document}
为什么它可以编译?
答案1
在amsopn.sty
我们看到
\newcommand{\DeclareMathOperator}{%
\@ifstar{\@declmathop m}{\@declmathop o}}
请注意,在这种情况下,@
是字母。在您的例子中,没有*
后续内容,因此 TeX 会将
\DeclareMathOperator{\G2}{G_2}
进入
\@declmathop o{\G2}{G_2}
现在我们寻找的定义\@declmathop
:
\long\def\@declmathop#1#2#3{%
\@ifdefinable{#2}{%
\DeclareRobustCommand{#2}{\qopname\newmcodes@#1{#3}}}}
所以我们得到
\@ifdefinable{\G2}{\DeclareRobustCommand{\G2}{\qopname\newmcodes@o{G_2}}}
嗯,看来罪魁祸首之一是\@ifdefinable
。确实
% latex.ltx, line 1287:
\long\def\@ifdefinable #1#2{%
\edef\reserved@a{\expandafter\@gobble\string #1}%
\@ifundefined\reserved@a
{\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%
\ifx \reserved@b\@qend \@notdefinable\else
\ifx \reserved@a\@qrelax \@notdefinable\else
#2%
\fi
\fi}%
\@notdefinable}
\G2
在您的情况下,我们有#1
,另一个支撑组是#2
:
\edef\reserved@a{\expandafter\@gobble\string\G2}
定义\reserved@a
为扩展为G2
,这很可能使\@ifundefined\reserved@a
返回 true。因此我们得到
\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}
\ifx \reserved@b\@qend
\@notdefinable
\else
\ifx \reserved@a\@qrelax
\@notdefinable
\else
\DeclareRobustCommand{\G2}{\qopname\newmcodes@o{G_2}}
\fi
\fi
(重新格式化,但实际上标记列表中没有结束行)。现在第一个测试和第二个测试都返回 false,因此您得到
\DeclareRobustCommand{\G2}{\qopname\newmcodes@o{G_2}}
这是第二个罪魁祸首,因为我们看到
% latex.ltx, line 1376:
\def\DeclareRobustCommand{\@star@or@long\declare@robustcommand}
% latex.ltx, line 1226:
\def\@star@or@long#1{%
\@ifstar
{\let\l@ngrel@x\relax#1}%
{\let\l@ngrel@x\long#1}}
% latex.ltx, line 1377:
\def\declare@robustcommand#1{%
\ifx#1\@undefined\else\ifx#1\relax\else
\@latex@info{Redefining \string#1}%
\fi\fi
\edef\reserved@a{\string#1}%
\def\reserved@b{#1}%
\edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}%
\edef#1{%
\ifx\reserved@a\reserved@b
\noexpand\x@protect
\noexpand#1%
\fi
\noexpand\protect
\expandafter\noexpand\csname
\expandafter\@gobble\string#1 \endcsname
}%
\let\@ifdefinable\@rc@ifdefinable
\expandafter\new@command\csname
\expandafter\@gobble\string#1 \endcsname
}
这\@star@or@long
部分与此无关,我们得到
\declare@robustcommand{\G2}{\qopname\newmcodes@o{G_2}}
并将其转化为
\ifx\G2\@undefined
\else
\ifx\G2\relax
\else
\@latex@info{Redefining \string\G2}%
\fi
\fi
(后面还有更多标记)。第一个条件\G
与比较2
,它们不同,因此\@undefined
被跳过,我们从这一部分中什么也得不到。接下来我们有了实际定义,基本上,LaTeX 最终会
\edef\G2{\noexpand\protect\expandafter\noexpand\csname G2 \endcsname}
\expandafter\def\csname G2 \endcsname{\qopname\newmcodes@o{G_2}}
\edef
如你所见,就 TeX 而言,第一个是合法的。事实上,如果你\show\G
在文件中这样做,你会得到
> \G=macro:
2->\protect \G2 .
意思就是\G
必须后面跟着一个明确的标记2
,组合将转换为\protect\G2•
(项目符号表示命令名称中的空格)。
如果你进一步做,也不会得到任何错误
\DeclareMathOperator{\G3}{G_3}
但是如果您尝试调用,则会引发错误\G2
,因为在它之后\G
已被重新定义为 want 3
。
可能\@ifdefinable
应该检查它的参数是否由单个标记组成。但事实并非如此。
无论如何,主要的TeX 的规则是宏名称仅由字母或单个非字母组成。