在接受的答案中这个问题介绍了一种交换宏的星号版本和非星号版本的方法\DeclarePairedDelimiter
。例如,对于该\abs
函数,我们可以使用
\makeatletter
\DeclarePairedDelimiter\tmp@abs{\lvert}{\rvert}
\def\abs{\@ifstar{\tmp@abs}{\tmp@abs*}}
\makeatother
这是一个很好的解决方案,因为的结果比和\DeclarePairedDelimiter
要好得多(特别是在间距方面),并且带星号的版本通常比无星号的版本更受欢迎,因此最好将其作为默认版本。\left
\right
有没有办法将上述方法组合成一个可以自动进行交换的宏?在这种情况下,这不是什么大问题,每个定义只有两行代码,但定义一个函数或宏来封装多次执行的过程通常被认为是最佳实践。在这种情况下,我认为合适的宏应该是这样的:
\makeatletter
\newcommand*\DeclarePairedDelimiterSwapped[3]{
\DeclarePairedDelimiter\tmp@delim{#2}{#3}
\def{#1}{\@ifstar{\tmp@delim}{\tmp@delim*}}
}
\makeatletter
\DeclarePairedDelimiterSwapped\abs{\lvert}{\rvert}
然后我可以继续定义许多分隔符,每个分隔符一行。但是,上面的代码会产生错误,事后看来,它显然不会起作用,因为它\abs
被视为输入而未定义。我该如何修复我的定义,\DeclarePairedDelimiterSwapped
以便它实际上定义命令?或者,如果这不是一个容易修复的问题,请告诉我。
答案1
你可以做到。但你应该这样做吗?你\abs{\hat{f}}
自己看看并判断吧。
\documentclass{article}
\usepackage{mathtools}
\ExplSyntaxOn
\NewDocumentCommand{\DeclarePairedDelimiterSwapped}{mmm}
{% first define \DeclarePairedDelimiter on a different command
\exp_args:Nc \DeclarePairedDelimiter { eddy @ \cs_to_str:N #1 } { #2 } { #3 }
% now define your swapped command
\NewDocumentCommand{#1}{som}
{
\IfBooleanTF { ##1 }
{% * is used, ignore the optional argument
\use:c { eddy @ \cs_to_str:N #1 } { ##3 }
}
{% no *
\IfNoValueTF { ##2 }
{% no optional argument
\use:c { eddy @ \cs_to_str:N #1 } * { ##3 }
}
{% optional argument
\use:c { eddy @ \cs_to_str:N #1 } [ ##2 ] { ##3 }
}
}
}
}
\ExplSyntaxOff
\DeclarePairedDelimiterSwapped{\abs}{\lvert}{\rvert}
\begin{document}
\[
\abs{\frac{1}{2}} % auto sizing
\quad
\abs{\hat{f}} % auto sizing
\quad
\abs*{\hat{f}} % no auto sizing
\quad
\abs[\big]{1} % big size
\quad
\abs[\Big]{\frac{1}{2}} % Big size
\]
\end{document}
这只是为什么应谨慎使用自动调整大小功能且不可滥用的原因之一。
现在您知道了,使用普通\DeclarePairedDelimiter
并添加*
仅有的当真正需要时(即非常罕见)。