在撰写统计物理学讲义时,我发现我经常写非常相似的长 LaTeX 序列,例如
\frac{\partial }{\partial <foo>}
\frac{\partial <bar>}{\partial <foo>}
和
\left( \frac{\partial <bar>}{\partial <foo>} \right)_{<baz>}
我想通过使用表格来简化我的生活
\dddfrac{<foo>}
\dddfrac{<foo>}{<bar>}
, 和
\dddfrac{<foo>}{<bar>}{<baz>}
它们都有相同的名称,因此很容易记住。
我的一个朋友(现在无法提供帮助)帮助我完成了以下 TeX 黑客攻击:
%requires \usepackage{gmverb}
\fooatletter{%
\def\dddfrac#1{%
\relaxen\dddfrac@i
\relaxen\dddfrac@ii
\relaxen\dddfrac@iii
\def\dddfrac@i{#1}%
\@ifnextchar\bgroup\dddfrac@getii\dddfrac@typeset}%
%
\def\dddfrac@getii#1{%
\def\dddfrac@ii{#1}%
\@ifnextchar\bgroup\dddfrac@getiii\dddfrac@typeset}%
%
\def\dddfrac@getiii#1{%
\def\dddfrac@iii{#1}%
\dddfrac@typeset}%
%
\def\dddfrac@typeset{%
\@ifundefined{dddfrac@iii}{%
\@ifundefined{dddfrac@ii}{% 1 argument only
\frac{\partial }{\partial \dddfrac@i}
}{% 2 arguments
\frac{\partial \dddfrac@i}{\partial \dddfrac@ii}%
}}{% 3 arguments
\left( \frac{\partial \dddfrac@i}{\partial \dddfrac@ii} \right)_{\dddfrac@iii}%
}}
}
我有使用 LaTeX 的经验,但不能用纯 TeX 书写(但我或多或少了解代码的作用)。
现在,虽然这可以正常工作,但如果我想要 20 个这样的命令,代码会写得非常长。对于一个人来说,是否有任何标准的方法来简化这种行为的实现?不知道如何用纯 TeX 编程吗?也许有人已经为这种情况编写了包,类似于例如包suffix
?
第二个问题:LaTeX 有一个传统,即为具有一些额外功能的命令引入带星号的版本,而不是在名称后加上后缀,例如“Ex”(就像微软所做的那样)。是否可以遵循 \dddfrac 命令的这一传统,并使用另一组定义来定义 \dddfrac*,以适应不同数量的参数?
Matbesuffix
会有帮助吗?毕竟,这个包允许定义带星号的命令版本,或者定义带有 1 个参数和不带有参数的命令版本。但文档相当短,需要 TeX 知识,我谦虚地希望没有 TeX 也能活下去。
答案1
这xparse
包已在其他答案中提及。这提供了一种通用方法来定义(类似 LaTeX2e)文档命令,而无需编程。有几种方法可以实现您想要的。一种方法是
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\dddfrac}{mG{}g}{%
\IfNoValueTF{#3}
{%
\frac
{\partial #2}
{\partial #1}%
}
{%
\left (
\frac{\partial #2}{\partial #1}
\right )
_{#3}
}%
}
\begin{document}
$\dddfrac{x}$
$\dddfrac{y}{f_y}$
$\dddfrac{y}{f_y}{n}$
\end{document}
这将设置\dddfrac
为需要一个强制参数(#1
)和两个“可选组”参数。第一个设置为G{}
,这意味着默认值为零。第二个设置为g
,如果没有给出,它将返回一个特殊标记\NoValue
。我用它来测试最后一个参数,然后可以用它来判断我们是否需要\left (
...\right )
对。我已经做过一次测试:你可以做两次,而不需要重复\frac
。
答案2
使用xparse
它可以轻松定义具有多个可选参数的命令。
\documentclass{scrartcl}
\usepackage{xparse}
\NewDocumentCommand{\dddfrac}{m O{} D(){}}{%
\def\@tempa{#3}%
\ifx\@tempa\@empty\else\left(\fi%
\frac{%
\partial #2
}{%
\partial #1
}
\ifx\@tempa\@empty\else\right)_{#3}\fi%
}
\begin{document}
$\dddfrac{x}$
$\dddfrac{y}[f_y]$
$\dddfrac{f(x)}(n)$
$\dddfrac{y}[f_y](n)$
\end{document}
解释
\NewDocumentCommand
工作原理类似,\newcommand
但将参数规范作为第二个参数。在参数规范中,我们使用 来
m
声明一个强制参数,O{<default>}
定义一个可选参数,并D<delim 1><delim 2>{<default>}
定义一个由<delim 1>
和分隔的可选参数<delim 2>
。您可以替换
D(){}
并O{}
使用\dddfrac{<foo>}[<bar>][<baz>]
我们将第三个参数存储
#3
在\@tempa
并通过\ifx
与它进行比较\@empty
,如果它为空,则我们不执行任何操作,否则(\else
)我们打印括号。\makatletter
可以@
成为控制序列的一部分
答案3
在 LaTeX 中,有一个名为 的命令\newcommand
。你可以用它编写小宏。
该命令的语法\newcommand
是:
\newcommand{\commandname}[numberOfArguments][defaultArgument]{implementation}
因此您可以按照以下方式编写宏:
\newcommand{\dddafrac}[1]{\ensuremath{\frac{\partial }{\partial #1}}}
\newcommand{\dddbfrac}[2]{\ensuremath{\frac{\partial #1}{\partial #2}}}
\newcommand{\dddcfrac}[3]{\ensuremath{\left( \frac{\partial #1}{\partial #2} \right)_{#3}}}
我认为这段代码的作用非常清楚。使用#1
它检索第一个参数。