我有点厌倦用 定义所有数学运算符\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
不会被抓住。
另一种方法是简化定义运算符:
\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}