\newcommand 和 \newcommand* 之间有什么区别?

\newcommand 和 \newcommand* 之间有什么区别?

我刚刚发现有人\newcommand*在回答中用到了它,然后才意识到我从来没有弄清楚星号在那里的用途。

(这个问题在互联网上几乎不可能搜索到,所以这里是记录答案的好地方!)

答案1

首先介绍一下背景。当 Knuth 编写 TeX 时,他意识到大多数宏不需要吸收多个段落作为参数。因此,测试诸如缺失之类的错误的一个好方法}是禁止宏接受段落标记(由空行或显式\par标记生成的标记)。因此,他创建了\def不能接受段落标记的定义,以及\long允许它们这样做的前缀:

\def\examplea#1{% #1 cannot contain \par
}
\long\def\exampleb#1{% #1 can contain \par
}

在编写 LaTeX 时,Lamport 创建了\newcommand一个包装器,其中\def包含各种错误检查。他发现段落标记可能会出现在奇怪的地方。所以他决定将其设为\newcommand“长”。当 LaTeX 团队接手 LaTeX2e 时,他们决定需要添加修饰符*来防止这种情况:

\newcommand{\examplea}[1]{% #1 can contain \par
}
\newcommand*{\exampleb}[1]{% #1 cannot contain \par
}

大多数情况下,\newcommand*是最佳选择,因为您需要它提供的错误检查。这就是为什么经验丰富的 LaTeX 用户给出的示例通常使用此形式,而不仅仅是\newcommand

可以看到相同的行为\newenvironment

\newenvironment{examplea}[1]{% #1 can contain \par
}{}
\newenvironment*{exampleb}[1]{% #1 cannot contain \par
}{}

这通过定义\examplea\endexamplea或多或少地使用\newcommand以及\exampleb\endexampleb或多或少地使用来实现\newcommand*来实现。因此,'end' 宏具有与 'begin' 宏相同的“长”状态,即使它们从不接受参数。(请注意,这不会影响可以进入身体环境,只有参数)环境的详细介绍见\newenvironment 和 \newenvironment* 之间有什么区别?

对于 LaTeX3,我们决定采用一种混合方法。如果您使用xparse来定义文档命令,则只有在您要求时它们才会“长”:

\NewDocumentCommand\examplea{m}{% #1 cannot contain \par
}
\NewDocumentCommand\examplab{+m}{% #1 can contain \par
}

(我们决定+表示一个长参数)。另一方面,对于内部使用,通常最好接受段落标记,并将过滤留给用户界面级别。

答案2

根据第二版LaTeX 伴侣:(第 846 页):

[ \newcommand*] 定义一个 [命令],在 TeX 术语中,它不是长的。这意味着新定义的命令不接受空行或\par

这也是 的默认行为\def,而无星号版本实际上等同于\long\def

答案3

这里:“使用带星号的版本\newcommand意味着定义的命令的参数不能包含空行或\par。这使得发现失控参数变得容易得多。”

答案4

在作者的 Latex2e(usrguide.pdf)中,我发现第 3.4 节与所有“defin-y”命令有关:

以上五个“定义命令”现在都具有 * 形式,这通常是定义带参数的命令时更好的形式,除非这些参数中的任何一个旨在包含整个文本段落。此外,如果您确实发现自己需要使用非星号形式,那么您应该问一下,是否最好将该参数视为适当定义的环境的内容。

相关内容