\providecommand 相当于 \DeclareMathOperator:\ProvideMathOperator?

\providecommand 相当于 \DeclareMathOperator:\ProvideMathOperator?

\providecommand相当于什么\DeclareMathOperator

即,当且仅当新命令尚未定义时,是否\providecommand才使用该方法定义新命令?\newcommand

实际上,正如 @egreg 在评论中指出的那样,这\providecommand可能是危险的,因为它可能会对定义它的包的行为产生不利影响。我真正想要的是将悄悄确保命令存在的能力与确保提供的定义与先前定义一致的\providecommand功能结合起来。\CheckCommand

答案1

我会非常谨慎地使用\providecommand或变体。这个简单的例子可以说明原因:如果你说

\providecommand{\box}{something}

然后开始\box在文档中使用,非常将会出现令人费解的错误信息。

人们可能会想到定义一个,\ProvideMathOperator它还会检查第一个参数的定义(如果已经以某种方式定义),并警告我们尝试定义的控制序列是否是运算符(具有相同的定义)。

然而这非常困难:提供的控制序列可能有任何定义,具有强制或可选参数,是健壮的,甚至是不可扩展的。

原则上,我们可以处理所有这些变化,但这相当困难(我向你保证确实如此)。毕竟,预定义的数学运算符的数量不是很多,因此“如果 LaTeX 报错,请使用\DeclareMathOperator并尝试其他名称”的方式看上去不太复杂。


这是一个相当简单的过程:

\documentclass{article}
\usepackage{amsmath,xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\ProvideMathOperator}{smm}
 {
  \cs_if_exist:NTF #2
   {
    \xopn_check:Nn #2 { #3 }
   }
   {
    \IfBooleanTF{#1}
      { \DeclareMathOperator*{#2}{#3} }
      { \DeclareMathOperator{#2}{#3} }
   }
 }
\cs_new_protected:Npn \xopn_check:Nn #1 #2
 {
  \cs_if_exist:cTF { \cs_to_str:N #1\c_space_tl }
   {
    \tl_set:Nx \l_xopn_name_tl { \token_get_replacement_spec:c { \cs_to_str:N #1 \c_space_tl } }
   }
   {
    \tl_set:Nx \l_xopn_name_tl { \token_get_replacement_spec:c { \cs_to_str:N #1 } }
   }
   \xopn_check_operator:Nn #1 { #2 }
 }
\cs_new_protected:Npn \xopn_check_operator:Nn #1 #2
 {
  \regex_match:nVTF { \A \\qopname\ \\(newmcodes@|relax)\ (o|m) \{ #2 \} \Z } \l_xopn_name_tl
    { \msg_warning:nnx { xopn } { samedefinition } { \token_to_str:N #1 } }
    { \msg_warning:nnxx { xopn } { differentdefinition } { \token_to_str:N #1 } { \l_xopn_name_tl } }
 }
\cs_generate_variant:Nn \regex_match:nnTF {nV}
\cs_generate_variant:Nn \token_get_replacement_spec:N {c}
\msg_new:nnn { xopn } { samedefinition }
 {
  The~operator~`#1'~already~exists~with~the~same~definition
 }
\msg_new:nnn { xopn } { differentdefinition }
 {
  The~command~`#1'~has~already~a~different~definition\\
  \\
  #2\\
  \\
  (If~the~above~reads~`\token_to_str:N \scan_stop:'~don't~
  redefine~`#1'~under~any~circumstances,~but~be~cautious~anyway)
 }
\ExplSyntaxOff

\ProvideMathOperator{\log}{log}
\ProvideMathOperator{\gcd}{gcd}
\DeclareMathOperator{\Tor}{Tor}
\ProvideMathOperator{\Tor}{Tor}

\ProvideMathOperator{\null}{null}
\ProvideMathOperator{\fi}{fi}

我只是尝试看看所提议的控制序列是否存在;后一种情况\DeclareMathOperator是安全的。在前一种情况下,我查看“名称中带有尾随空格的命令”是否存在;然后我将命令的含义(如果存在,则使用带有尾随空格的命令)与amsmath如果它是运算符则定义它的含义进行比较。

该文件的输出是

*************************************************
* xopn warning: "samedefinition"
* 
* The operator `\log' already exists with the same definition
*************************************************
*************************************************
* xopn warning: "samedefinition"
* 
* The operator `\gcd' already exists with the same definition
*************************************************
*************************************************
* xopn warning: "samedefinition"
* 
* The operator `\Tor' already exists with the same definition
*************************************************
*************************************************
* xopn warning: "differentdefinition"
* 
* The command `\null' has already a different definition
* 
* \hbox {}
* 
* (If the above reads `\scan_stop:' don't redefine `\null' under any
* circumstances, but be cautious anyway)
*************************************************
*************************************************
* xopn warning: "differentdefinition"
* 
* The command `\fi' has already a different definition
* 
* \scan_stop: 
* 
* (If the above reads `\scan_stop:' don't redefine `\fi' under any
* circumstances, but be cautious anyway)
*************************************************

当发出警告时,不执行任何定义。

\ProvideMathOperator*像 一样接受-variant \DeclareMathOperator

答案2

我认为不存在这样的命令amsmath,但您可以使用创建自己的命令\ifdefined

\documentclass{article}
\usepackage{amsmath}
\newcommand\ProvideMathOperator[2]{\ifdefined#1\else\DeclareMathOperator{#1}{#2}\fi}
\DeclareMathOperator{\goat}{goat}
\ProvideMathOperator{\sheep}{sheep}
\ProvideMathOperator{\goat}{} %Has no effect because \goat is already defined.
\begin{document}
$\goat$ $\sheep$ 
\end{document}

相关内容