为什么“MathOperator”的名称可以包含数字?

为什么“MathOperator”的名称可以包含数字?

这不能编译,这正是我所期望的:

\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 的规则是宏名称仅由字母或单个非字母组成。

相关内容