\DeclareMathOperator 的替代方案

\DeclareMathOperator 的替代方案

我有点厌倦用 定义所有数学运算符\DeclareMathOperator。而且将它们作为宏很少有用。相反,它有时会导致宏名称冲突(例如\span)。所以我想出了以下内容:

\documentclass{article}
\usepackage{amsmath}
\catcode`\¡=\active
\def¡#1!{\operatorname{#1}}
\begin{document}
    \[e^{ix} = ¡cos! x + i¡sin! x\]
\end{document}

我想删除!末尾的 ,也许使用\ifmmode, 以允许¡在普通文本中使用。这可能吗?我的定义是否还有其他我应该注意的副作用?

答案1

你从一个错误的前提开始:这是好的对于经常使用的结构和数学运算符(例如“正弦”和“对数”)有宏也不例外。

如果一个操作符只出现几次,那么使用

\operatorname{foo}

针对这几种情况?如果你不想输入太多,那么

\newcommand{\op}[1]{\operatorname{#1}}

允许简单输入

\op{foo}

这仅比您建议的语法多需要三个击键。

很难有一个安全的例程来扫描名称,就像 TeX 扫描控制序列一样。控制序列名称的扫描是内置的,而您应该逐个字符地进行扫描,并在扫描过程中存储它们,直到找到非字母的内容。

还有另外一个问题:¡如果文档是在以下情况下编译的,你提议的字符肯定不会起作用:

\usepackage[utf8]{inputenc}

因为在这种情况下它不是一个字符,而是两个:它的 UTF-8 表示是0xC2A1。您可以改用`, 。

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

\ExplSyntaxOn
\tl_new:N \l__canaaerus_name_tl

\cs_new_protected:Npn \canaaerus_bq_mathop:
 {
  % clear the container
  \tl_clear:N \l__canaaerus_name_tl
  % start the recursion
  \canaaerus_absorb:
 }

\cs_new_protected:Npn \canaaerus_absorb:
 {
  \peek_catcode:NTF a
   {% if the next token is a letter absorb it
    \__canaaerus_absorb_next:n
   }
   {% otherwise produce the operator name
    \__canaaerus_deliver:
   }
 }

\cs_new_protected:Npn \__canaaerus_absorb_next:n #1
 {
  % add the next letter to the container
  \tl_put_right:Nn \l__canaaerus_name_tl { #1 }
  % restart the recursion
  \canaaerus_absorb:
 }

\cs_new_protected:Npn \__canaaerus_deliver:
 {
  % produce the operator name
  \operatorname{\l__canaaerus_name_tl}
 }

% define the active back quote
\group_begin:
\char_set_catcode_active:N `
\cs_gset_eq:NN ` \canaaerus_bq_mathop:
\group_end:
\ExplSyntaxOff

% make the backquote math active
\AtBeginDocument{\mathcode``=\string"8000 }

\begin{document}

$`cos(\alpha+\beta)-`sin x$

\end{document}

效率极低,但有效。当然,语法错误,例如输入

`sinx

不会被抓住。

enter image description here

另一种方法是简化定义运算符:

\documentclass{article}
\usepackage{xparse,amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\DeclareMathOperators}{m}
 {
  \keys_set:nn { canaaerus/mathop } { #1 }
 }

\keys_define:nn { canaaerus/mathop }
 {
  unknown .code:n = \canaaerus_defop:n { #1 }
 }

\cs_new_protected:Npn \canaaerus_defop:n #1
 {
  \cs_if_exist:cTF { \l_keys_key_tl }
   {
    \msg_error:nnx { canaaerus/mathop } { exist } { \exp_not:c { \l_keys_key_tl } }
   }
   {
    \tl_if_empty:nTF { #1 }
     {
      \cs_new:cpx { \l_keys_key_tl } { \exp_not:N \operatorname { \l_keys_key_tl } }
     }
     {
      \cs_new:cpx { \l_keys_key_tl } { \exp_not:N \operatorname { #1 } }
     }
   }
 }
\msg_new:nnnn { canaaerus/mathop } { exist }
 {
  #1 already~defined
 }
 {
  The~command~#1 already~exists,~ignored
 }
\cs_generate_variant:Nn \msg_error:nnn { nnx }
\ExplSyntaxOff

\DeclareMathOperators{
  Tor,
  Hom,
  Span=span,
  %span, % if uncommented it would raise an error
}

\begin{document}
$\Tor\quad\Hom\quad\Span$
\end{document}

相关内容