以正确的方式定义新命令名称

以正确的方式定义新命令名称

我想定义一个简短的命令名称\gm{a,b},在 LaTeX 中

\overset{a\to b}\longrightarrow 

我自己尝试过。下面的代码仅适用于\gm{a}(或\gm{b}将 a 更改为 b)

\newcommand{\gm}[1]{\overset{#1\to b}\longrightarrow}

但我无法让它同时对 a 和 b 起作用,这样\gm{a,b}才能起作用。

答案1

如果你想解析逗号,你可以做类似下面的事情

\makeatletter
\def\my@gm#1,#2\@nil{\overset{#1\to#2}\longrightarrow}
\newcommand\gm[1]{\my@gm#1\@nil}
\makeatother

当然,这取决于您是否记得使用逗号。省略逗号将导致错误。

答案2

虽然你可以让\gm{a,b}语法发挥作用,正如 A. Ellett 的回答所示,但我认为首先要意识到的是,这种语法反对TeX 的基本机制,即首先将括号内的每个标记列表(本身与括号相平衡)分组为一个单元。这意味着最初a,b将被视为一个单元,这不是您想要的。可以绕过这一点的原因是,一旦用于分组,括号就会消失(识别为不是 {a,b}) 这样通过将它们放在不同的上下文中并重新解析(第二次匹配逗号),就可以产生不同的细分。

因此,您建议使用的语法可以仅有的可以通过双重解析来处理(并使用辅助宏来实现),因此它不是传递参数的标准方式。您可以让它工作,但它看起来不像其他宏调用的语法,因此往往会让使用它阅读 TeX 源代码的人感到困惑;最后可能您自己也会感到困惑。

LaTeX 在输入语法方面设计得非常保守,鼓励用户将几乎所有(小的)用作单位的东西用括号括起来。(有时甚至到了推行荒谬习惯的地步,将不可能超过一个标记的东西分组,例如由 定义的名称\newcommand:它不可能一次定义多个名称,因此括号在这里完全没用,但 LaTeX 手册似乎出于某种原因想要推广这种习惯,我不明白。)LaTeX 建议的语法(如果您坚持\newcommand只使用则强制执行)是使用括号括起来每个参数分开。并且不使用任何其他东西(例如逗号)。如\gm{a}{b}。这就是在简单定义之后起作用的

\newcommand\gm[2]{\overset{{#1}\to{#2}}\longrightarrow}

这要求您在每次调用时比您建议的语法多输入一个字符;但为了获得更好的可读性,这并不是很大的代价。

Basic TeX 确实为您提供了更灵活的调用语法,允许使用括号以外的其他东西来分隔参数。因此,它允许使用括号和逗号(或任何字符)来分隔参数除了括号)与调用语法一样\gm(a,b),在定义之后

\def\gm(#1,#2){\overset{{#1}\to{#2}}\longrightarrow}

现在,每次调用都需要字符(, , ,)并且 TeX 会向前扫描直到找到它们,从而使 到 之间的任何参数成为可能\gm(但由于 之前没有参数(,因此该符号必须紧跟在 之后\gm,这可能是件好事,因为它允许对未使用正确语法的调用发出警告)。请注意,该机制非常原始且贪婪;如果您编写\gm(a,b,c)它不会抱怨参数太多,而是将ab,c作为两个参数传递给\gm。另请注意,括号仍可用于分组:\gm({a,b},c)将防止第一个逗号充当分隔符,并将a,bc作为两个参数传递给\gm(请注意,在 发挥作用后括号会消失)。我个人喜欢不时使用这种替代语法(您甚至可以\gm(a->b)在这里选择)。但不要过度使用,因为混合输入语法会造成混淆。

最后要说的是,我在上面的定义中写成了{#1}and ,{#2}而不是#1and #2。这是一个好习惯,成本不高(它只会延长定义,而不会延长调用),并且可以防止参数在宏定义中“崩溃”的意外(尽管这可能不是这个特定定义中的问题)。请记住,一旦解析了调用,TeX 就会删除宏调用中使用的任何外部括号,因此即使您在调用中用括号括住参数,替换为#1and的值#2也不会包含这些括号。

相关内容