何时不应使用 \ensuremath 作为数学宏?

何时不应使用 \ensuremath 作为数学宏?

我已经养成了\ensuremath每一个我定义的宏,这样我就可以在数学模式内外使用相同的宏。但 egreg 的评论\DeclareMathOperator 不接受参数让我思考也许我不应该总是这样做:

我认为添加 不是一个好主意;为什么要添加?免责声明:这是我的“仅在真正需要时”活动\ensuremath的一部分。:) -\ensuremath埃格尔

相关评论在对齐环境中,强制在 \lim 参数内换行

为什么\ensuremath$\scriptstyle#1$阅读起来不是更容易吗? -埃格尔

在这种情况下,需要使用数学模式,因为我们处于\makebox(即文本模式)中。因此,出于习惯,我使用了,\ensuremath但 egreg 是对的,在这种情况下使用$...$效果同样好,而且肯定更容易阅读。但是,即使在这种情况下,我仍然更喜欢使用,\ensuremath这样更明显地表明它可以在数学和文本模式下使用,而不必考虑\makebox在文本模式下。

\ensuremath那么,至少对于我的任何个人宏来说,一直使用 真的有什么坏处吗?我意识到在处理过程中会有一点额外的开销,但还有其他需要考虑的吗?

如果宏在用于通用目的的软件包中还有其他注意事项,我也会对此感兴趣。最明显的一点是,我们可能希望确保宏的用户知道该宏需要数学模式,因此要求他们仅在数学模式下使用该宏。

由于这引用了 egreg 的竞选活动,我觉得我应该包括一个平均能量损失对于新用户,按照我的 MWE-as-often-as-possible 活动:

\documentclass{article}

\newcommand{\FunctionF}{\ensuremath{x^2}}%

\begin{document}
Text mode: \FunctionF

Math mode: $G(x) = x^3 - \FunctionF$
\end{document}

答案1

我想到两个反对意见:

  • 如果您不知道自己将进入数学模式,那么您可能会写出一些“语义上”正确但却不准确的东西。

例如:

\documentclass{article}
\newcommand\mathmacro[1][A]{\ensuremath{{#1}_1}}
\begin{document}
 \mathmacro[$x^2$] % The dollar signs *leave* math mode
\end{document}

这里发生的事情是\mathmacro[$x^2$]扩展为

\ensuremath{{$x^2$}_1}

扩展为(有效)

\ifmmode
 {$x^2$}_1
\else
 ${$x^2$}_1$
\fi

你会发现如果你这样写外部数学模式,则采用第二个分支,因此第一个美元符号将您带入数学模式,而前面的美元符号$x^2$将您带出数学模式,随后将发生逆操作。这会产生错误。

当然,你不应该这样做,因为它\mathmacro实际上是一个“可在文本模式下使用的数学宏”,所以你应该将其参数括号内的内容视为数学模式。唉,这会让作者和文本编辑器的语法突出显示都感到困惑,因为这是一个非标准假设。

编辑:我将这个宏定义为:

\newcommand\mathmacro[1][A]{{#1}_1}

并将其用作:

$x^2$ sub one: $\mathmacro[x^2]$.

这样,数学的部分就清晰明了了。

  • 万一您或某些软件包发生了这样的情况\everymath,当您的文本模式宏开始看起来不同时,您会感到非常惊讶。

不过,就语义而言,问题很明显:\ensuremath打破了数学和文本之间的区别,这是两个截然不同的东西。TeX 甚至内置了区别:不同的字体、不同的间距规则、不同的解析规则。利用这些,你很可能可以构造出更多的反例。

我的意思是,在以下情况下:

\documentclass{article}
\newcommand\mathmacro[1][A]{\ensuremath{{#1}_1}}
\begin{document}
 A sub one: \mathmacro

 \bfseries A sub one: \mathmacro
\end{document}

您可能会感到惊讶,粗体文本并没有延伸到明显的文本模式的内容\mathmacro

我要说的并不是\ensuremath 实际上破坏任何事情,因为它违背了你的期望,使事情变得更难而不是更容易。

答案2

没有什么不好的\ensuremath 本身。然而,如果我们检查你这个问题我认为能够\FunctionF同时在文本模式和数学模式下说没有任何好处,而不是总是坚持\(\FunctionF\)(或者$\FunctionF$像其他人可能喜欢的那样)。TeX.SX 上还有许多其他帖子也这样做。采取这个:如果一个人想要那个命令的话,那么能够写the ring~\Z{n}而不是写有什么好处呢the ring~$\Z{n}$?也许,一个人还必须写the ring $\Z{m}\times\Z{n}$,而这很有可能?

另一篇帖子有以下代码:

\newcommand{\vrel}[3]{
\vcenter{\halign{\hfill##\hfill\cr
\ensuremath{#1}\cr
\rotatebox[origin=c]{270}{\ensuremath{#2}}\cr
\ensuremath{#3}\cr
}}}

在我看来,这是糟糕的编程,因为里面的内容\ensuremath 在数学模式下排版;“正确”的代码应该是

\newcommand{\vrel}[3]{
\vcenter{\mathsurround=0pt \halign{\hfill##\hfill\cr
  $#1$}\cr
  \rotatebox[origin=c]{270}{$#2$}\cr
  $#3$\cr
}}}

\ensuremath其他使事情变得比必要更复杂的情况包括这个这个

答案3

用户 egreg 的评论针对这个问题为什么这么多符号被限制在数学模式中?“非常有价值:

如果允许这样做,人们就会写错\alpha+\beta空格。数学应该始终被视为数学,即使是单个符号;如果您愿意,可以将其视为标记。

简单地说,使用\ensuremath可以很容易地教会相关宏的用户懒于明确切换到数学模式(如果没有上标或下标,则通常“不需要”所有符号都出现在页面上),结果是表达式的间距可能错误如果表达式应该遵循数学模式间距,但却以水平文本模式排版。这违背了 (La)TeX 的一个目的,即正确排版数学表达式。

如果用户在应该输入“ ”的地方输入了“ \myalpha+\mybeta”(或“ \myalpha + \mybeta”,那么不应该是“ \myalpha{} + \mybeta{}”吗?等等)\(\myalpha+\mybeta\),这可能会导致不良习惯,导致间距不正常。

答案4

我认为答案已在中提供fixltx2e,尽管在大多数情况下我不认为这是一个问题,但从文档中可以看出:

4.4.1 实施策略注意事项

Pr/3400\@fnsymbol决定在文本模式和数学模式之间做出选择,这需要一定的稳健性,因为必须在排版时而不是在内部\protected@edef或类似命令中做出文本和数学之间的决定。处理这个问题的一种方法是确保看到的值\@fnsymbol是一个完全扩展的数字,这可以通过以下代码来处理

\def\fnsymbol#1{\expandafter\@fnsymbol
  \expandafter{\the\csname c@#1\endcsname}}

如果每个人都只通过编写代码来使用高级命令,那么这将是一个很好的解决方案\fnsymbol{footnote}。不幸的是,许多类(包括标准类)和包直接使用内部形式,因此\@fnsymbol\c@footnote 更改的简单解决方案\fnsymbol会破坏过去 20 年来一直有效的代码。

因此,这里的实现\@fnsymbol再次使自己成为一个非健壮命令,而是使用一个新的健壮命令 \TextOrMath,它将负责排版数学或文本符号。为了做到这一点,我们面临 TeX 中一个古老的问题和无法解决的问题:对数学模式进行可靠的测试,而不会破坏字距调整。幸运的是,这个问题可以在使用 eTeX 时得到解决,因此如果您按照 LaTeX3 项目的建议使用它作为 LaTeX 格式的引擎,您将获得一个功能齐全的 \TextOrMath命令,而没有副作用。如果您使用常规 TeX 作为 LaTeX 格式的引擎,那么我们必须在两害相权取其轻:1) 破坏连字并阻止字距调整或 2) 面临在对齐单元格开头选择文本模式的风险,而对齐单元格应该是数学模式。我们决定 1) 按照 LaTeX 中常规健壮命令的习惯。

相关内容