我的问题是关于重新定义其他辅助命令的命令的设计。为了提出我的问题,我需要给出一个小的设置来描述我的意思。让我们从我的个人序言中取出一些辅助命令,并针对这个问题进行一些小的修改:
\DeclarePairedDelimiter{\parenth}{(}{)}
\providecommand{\intvar}{}
\ProvideDocumentCommand{\integral}{s m m e{_^}}{%
\renewcommand{\intvar}{#2}
\int%
\IfValueT{#4}{_{#4}}%
\IfValueT{#5}{^{#5}}%
\IfBooleanTF{#1}{\parenth*{#3}}{#3}%
\odif{#2}%
}
\ProvideDocumentCommand{\fourier}{s m m m E{_^}{{-\infty}{\infty}}}{%
\IfBooleanTF{#1}{%
\integral*{#2}{{#4}e^{-2\pi i{#2}{#3}}}_{#5}^{#6}%
}{%
\integral{#2}{{#4}e^{-2\pi i{#2}{#3}}}_{#5}^{#6}%
}%
}
为了省去您解读命令的麻烦,它们采用 和 的形式\integral{variable}{body}_{from}^{to}
,\fourier{var from}{var to}{body}_{from}^{to}
其中下标和上标是可选的。现在,请注意我对命令 的使用\intvar
。为了回答这个问题,我已将其添加到\integral
命令定义中。其目的是允许用户获取积分的积分变量。例如:
\begin{gather*}
\integral{x}{f(\intvar) g(\intvar)}_{0}^{1}\\
\fourier{t}{\xi}{f(\intvar)}
\end{gather*}
给我们:
如果我们改变积分变量,但不改变主体:
\begin{gather*}
\integral{z}{f(\intvar) g(\intvar)}_{0}^{1}\\
\fourier{\theta}{\xi}{f(\intvar)}
\end{gather*}
我们得到了预期的结果:
因此,我的问题涉及这样的情况,您可以\integral
在另一个\integral
命令(或派生命令,例如\fourier
)中使用 。这样做显然意味着 会\intvar
像预期的那样接受该“级别”的变量。例如:
\begin{gather*}
\integral{x}{f(\intvar)\integral{y}{g(\intvar)}}
\end{gather*}
给予:
但是,此代码仍然相当危险,并且可能会产生文档永远无法编译的情况。例如,此处\intvar
永远无法编译:\integral{x}{\fourier{\intvar}{...}{...}}
因为它尝试将的值设置\intval
为\intval
,然后是递归的。(如何处理才能使这种情况永远不会发生?)
我的问题是:如何正确编写带有此类内部定义命令的宏?说实话,我从未想过需要这样做。但这个例子很有趣,我想到了很多,希望能了解更多。
这是通过更仔细的设计考虑和测试来实现的,还是通过更高级的 expl3 来实现的?是否有可帮助完成此类任务的软件包?
此外,您能否设计一个可以\intvar
从更高级别引用的案例?例如,如果我想引用当前积分范围周围的积分的积分变量。在这种情况下,\intvar
只会引用该范围的积分变量。这是可以毫不费力完成的事情吗?如果是这样,人们会如何定义这样的命令(例如,他们使用什么工具:包、低级宏等)?还有其他需要考虑的因素吗?
答案1
使用分组。
还可以减少代码重复。
\documentclass{article}
\usepackage{mathtools}
\newcommand{\odif}{\mathop{}\!d}
\DeclarePairedDelimiter{\parenth}{(}{)}
\providecommand{\intvar}{}
\NewDocumentCommand{\integral}{s m m e{_^}}{%
\begingroup
\renewcommand{\intvar}{#2}%
\int
\IfValueT{#4}{_{#4}}%
\IfValueT{#5}{^{#5}}%
\IfBooleanTF{#1}{\parenth*{#3}}{#3}%
\odif#2%
\endgroup
}
\NewDocumentCommand{\fourier}{s m m m E{_^}{{-\infty}{\infty}}}{%
\expanded{\integral\IfBooleanT{#1}{*}}%
{#2}{{#4}e^{-2\pi i{#2}{#3}}}_{#5}^{#6}%
}
\begin{document}
\begin{gather*}
\integral{x}{f(\intvar) g(\intvar)}_{0}^{1} \\
\fourier{t}{\xi}{f(\intvar)} \\
\integral{x}{f(\intvar)\integral{y}{g(\intvar)}} \\
\integral*{x}{f(\intvar) + g(\intvar)}_{0}^{1} \\
\fourier*{t}{\xi}{f(\intvar)} \\
\integral{x}{f(\intvar)\integral*{y}{g(\intvar)+2}}
\end{gather*}
\end{document}
然而,我不建议\parenth*
随意使用。