重命名命令时是否应该指定参数?

重命名命令时是否应该指定参数?

为了获得语义代码,我想定义一个\closure具有与 相同效果的命令\overline。最初,我认为实现此目的的最简单方法是:

\newcommand{\closure}[1]{\overline{#1}}

但是,然后我尝试在定义中去掉参数的使用,我发现我可以这样写:

\newcommand{\closure}{\overline}

这两种定义方式\closure似乎都有效。因此,我有两个问题:(a) 第一个定义和第二个定义之间有什么区别吗?如果没有区别,(b) 一种方法是否比另一种更“正确”?

答案1

完整形式

\newcommand{\closure}[1]{\overline{#1}}

\overline不喜欢\par。它会抛出错误:

! Missing $ inserted.

\closure因此,使用非参数来包含限制是有意义的\long

\newcommand*{\closure}[1]{\overline{#1}}

现在错误信息是:

Runaway argument?
{...
! Paragraph ended before \closure was complete.

对于用户来说更加清晰。

优点:

  • 定义很容易理解。
  • 如果参数不能是\long(不允许使用标记),则应通过 的星号形式\par将命令定义为不是。然后错误消息更加用户友好,显示更高级别命令的错误。\long\newcommand

坏处:

  • 运行时间损失较小。

没有参数

\newcommand{\closure}{\overline}
\newcommand*{\closure}{\overline}

星号形式或非星号形式通常并不重要,因为宏没有参数。

优势:

  • 高效的。

坏处:

  • 显示错误\overline,但用户已使用\closure

\let形式

\let\closure\overline

可以使用,如果\overline不改变的话。否则在定义时\closure具有的含义。\overline

优势:

  • 最有效率。

缺点:

  • 有时\let还不够。例如,带有可选参数的宏或通过 的健壮宏\DeclareRobustCommand。在内部,这些宏定义了另一个宏,对基本名称进行了小幅修改(例如,名称中附加了空格作为名称的一部分)。简单的 无法捕获这种情况。在这些情况下,带有的\let包会有所帮助。letltxmacro\LetLtxMacro

  • 底层命令不应该改变,否则定义的宏\let仍然具有旧的含义。

  • 如果命令已定义,\let则会在不发出警告的情况下覆盖它。可以通过以下方法修复此问题:

    \newcommand{\closure}{}% throws an error, if \closure is defined
    \let\closure\overline
    

相关内容