\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}