What is the rationale for requiring \DeclareMathOperator
to be in the preamble?
Why are users not allowed to restrict the scope of an operator definition to a particular chapter or environment, like \newcommand
?
amsmath
What is the rationale for requiring \DeclareMathOperator
to be in the preamble?
Why are users not allowed to restrict the scope of an operator definition to a particular chapter or environment, like \newcommand
?
I'd be very cautions in using \providecommand
or variations thereof. This simple example may show why: if you say
\providecommand{\box}{something}
and then start using \box
in your document, very puzzling error messages will be raised.
One might think to define a \ProvideMathOperator
that also checks for the definition of the first argument, if already defined somehow, and warns if the control sequence we are trying to define is an operator (with the same definition) or not.
However this is quite hard: the supplied control sequence might have any definition, with mandatory or optional arguments, be robust or even be unexpandable.
One could deal with all these variations, in principle, but it's rather hard (I assure you it really is). The number of predefined math operators is not very big, after all, so the "use \DeclareMathOperator
and try with another name if LaTeX complains" way seems to be the less complicated one.
Here's a rather simplistic procedure:
\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}
I just try and see whether the proposed control sequence exists or not; in the latter case \DeclareMathOperator
is safe. In the former case, I look whether the "command with trailing space in the name" exists; then I compare the meaning of the command (using the one with the trailing space, if existent) to what amsmath
would have defined it if it's an operator.
The output of the document is
*************************************************
* 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)
*************************************************
When the warning is issued, no definition is performed.
\ProvideMathOperator
accepts the *
-variant just like \DeclareMathOperator
.
For the selected structures, use as first optional argument the counter of the structure you initially subordinated to the section counter, so the selected structures will share the counter. For example, after yo do
\newtheorem{thm}{Theorem}[section]
the counter thm
for the Theorem
structure is subordinated to the section
counter, and defining
\newtheorem{lem}[thm]{Lemma}
makes the lem
counter share the counter for Theorem
structure. A complete example:
\documentclass{article}
\usepackage{amsthm}
\theoremstyle{plain}
\newtheorem{thm}{Theorem}[section]
\newtheorem{lem}[thm]{Lemma}
\newtheorem{cor}[thm]{Corollary}
\theoremstyle{definition}
\newtheorem{defn}[thm]{Definition}
\newtheorem*{ex}{Example}
\newtheorem{prop}[thm]{Proposition}
\theoremstyle{remark}
\newtheorem*{rem}{Remark}
\begin{document}
\section{Test}
\begin{thm}test\end{thm}
\begin{lem}test\end{lem}
\begin{prop}test\end{prop}
\begin{defn}test\end{defn}
\end{document}
Best Answer
In the case of
\DeclareMathOperator
, contrarily to theLaTeX
issues raised in this question: Why does LaTeX make \DeclareMathSymbol and \DeclareSymbolFont preamble-only?, the user is provided with a simple possibility to circumvent theonly-preamble
restriction: it is to use the\operatorname
or\operatornamewithlimits
command, also provided byamsmath
(or more preciselyamsopn
where\DeclareMathOperator
is defined and made preamble only).As an aside, there is an issue with
\DeclareMathOperator
and Unicode engines (if the minus sign is made a Unicode math character), which is fixed underlualatex
by loading package lualatex-math