我想定义一个命令\NewSmartOp
如下:
\NewSmartOp \MYOP \myop
将产生以下代码(或任何等效代码):
\makeatletter
\def\MYOP{\@ifstar\MYOP@star\MYOP@nostar}
\def\MYOP@star#1{\myop\!\left( #1 \right)}
\def\MYOP@nostar#1{\myop #1}
\makeatother
我想我需要\expandafter
,也许\csname … \endcsname
,但除此之外,我不知道如何生成这些定义,特别是关于如何\MYOP@star
从中形成一个新的命令名称\MYOP
,以及如何处理这些#1
必须在生成的定义中保持原样的定义(与通过生成它们的定义进行扩展相反)。
背景(可选阅读)
简单介绍一下背景:当我输入数学时,我希望尽可能地从具体语法中抽象出来。例如,对于集合的基数年代,也许我希望它被渲染为卡 S(仅在需要时使用括号,例如卡(S₁∪S₂)),但也许在未来的某个时候,我想将语法切换为|S|。因此,我会定义:
\DeclareMathOperator \card {card}
\NewSmartOp \CARD \card % option 1
%\newcommand* \CARD[1] {\left\lvert # \right\rvert} % option 2
之后
- 我可能会直接使用运算符(低级,我的 TeX 类型反映了具体的语法):
\card S
或\card(S)
; - 但我宁愿使用带有参数的命令,我将具体语法推迟到该参数(高级语法,我的 TeX 类型反映了抽象语法树)
\CARD {S}
:。
这个理想似乎很难完全实现,因为我无法自动找出何时需要括号,所以我采取的折衷方案是让这些“智能运算符”的起始版本添加括号:\CARD* {S_1 \cup S_2}
。
答案1
我不确定为什么不直接定义\CARD
:
\NewDocumentCommand{\CARD}{sm}{%
\operatorname{card}%
\IfBooleanT{#1}{\left(}%
#2%
\IfBooleanT{#1}{\right)}%
}
如果你想要一个抽象版本:
\NewDocumentCommand{\NewOP}{mm}{%
\NewDocumentCommand{#1}{sm}{%
\operatorname{#2}%
\IfBooleanT{##1}{\left}(%
##2%
\IfBooleanT{##1}{\right})%
}%
}
所以你可以\NewOp{\CARD}{card}
但是,使用\left(
and\right)
会产生不必要的超大括号。我已警告您。
您可以使用\DeclarePairedDelimiter
from mathtools
。
\documentclass{article}
\usepackage{amsmath,mathtools}
\NewDocumentCommand{\NewOp}{mm}{%
\NewDocumentCommand{#1}{t+s}{%
\operatorname{#2}
\IfBooleanT{##1}{%
\IfBooleanTF{##2}{\parentheses*}{\parentheses}%
}%
}%
}
\DeclarePairedDelimiter{\parentheses}{(}{)}
\NewOp{\card}{card}
\begin{document}
\begin{gather*}
\card{S} \\
\card+{S_1\cup S_2} \\
\card+{\hat{S}_1\cup\hat{S}_2} \\
\card+[\big]{\hat{S}_1\cup\hat{S}_2} \\
\card+*{\hat{S}_1\cup\hat{S}_2}
\end{gather*}
\end{document}
在命令后面加上 表示需要括号+
。这将调用成对的分隔符,而*
表示需要自动调整大小的分隔符。
然而,从最后一行可以看出结果并不理想。
答案2
这种“高级”、抽象、语义的语法或多或少正是我的包的目的semantex
:
\documentclass{article}
\usepackage{semantex}
\NewVariableClass\MyVar[output=\MyVar]
\NewObject\MyVar\card{\operatorname{card}}
\begin{document}
\begin{gather*}
\card{S} \\
\card[par]{S} \\
\card[no par]{S} \\
\card{ \hat{S}_1 \cup \hat{S}_2 } \\
\card[par=\big]{ \hat{S}_1 \cup \hat{S}_2 } \\
\card[par=auto]{ \hat{S}_1 \cup \hat{S}_2 }
\end{gather*}
\SetupObject\card{no par}
\begin{gather*}
\card{S} \\
\card[par]{S} \\
\card[no par]{S} \\
\card{ \hat{S}_1 \cup \hat{S}_2 } \\
\card[par=\big]{ \hat{S}_1 \cup \hat{S}_2 } \\
\card[par=auto]{ \hat{S}_1 \cup \hat{S}_2 }
\end{gather*}
\SetupObject\card{
symbol={},
par,
left par=\lvert,
right par=\rvert,
}
\begin{gather*}
\card{S} \\
\card[par]{S} \\
\card[no par]{S} \\
\card{ \hat{S}_1 \cup \hat{S}_2 } \\
\card[par=\big]{ \hat{S}_1 \cup \hat{S}_2 } \\
\card[par=auto]{ \hat{S}_1 \cup \hat{S}_2 }
\end{gather*}
\end{document}