![以正确的方式定义新命令名称](https://linux22.com/image/289127/%E4%BB%A5%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%96%B9%E5%BC%8F%E5%AE%9A%E4%B9%89%E6%96%B0%E5%91%BD%E4%BB%A4%E5%90%8D%E7%A7%B0.png)
我想定义一个简短的命令名称\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)
它不会抱怨参数太多,而是将a
和b,c
作为两个参数传递给\gm
。另请注意,括号仍可用于分组:\gm({a,b},c)
将防止第一个逗号充当分隔符,并将a,b
和c
作为两个参数传递给\gm
(请注意,在 发挥作用后括号会消失)。我个人喜欢不时使用这种替代语法(您甚至可以\gm(a->b)
在这里选择)。但不要过度使用,因为混合输入语法会造成混淆。
最后要说的是,我在上面的定义中写成了{#1}
and ,{#2}
而不是#1
and #2
。这是一个好习惯,成本不高(它只会延长定义,而不会延长调用),并且可以防止参数在宏定义中“崩溃”的意外(尽管这可能不是这个特定定义中的问题)。请记住,一旦解析了调用,TeX 就会删除宏调用中使用的任何外部括号,因此即使您在调用中用括号括住参数,替换为#1
and的值#2
也不会包含这些括号。