为了获得语义代码,我想定义一个\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