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

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

灵感来自关于\let和的问题\def,我有一些基本上都归结为问

\def和之间有什么区别\newcommand

我特别想知道

  1. 是否可以将\def可选参数和必需参数传递给 ed 命令?
  2. 是否有\redef等效于的命令\renewcommand
  3. 我只用过\newcommand——有什么理由我应该改变这个习惯吗?

但我欢迎对我可能没有想到的此列表中的任何其他内容发表评论!

答案1

\def是 TeX 原语,\newcommand是 之上的 LaTeX 覆盖层\def。 最明显的好处\newcommand\def

  1. \newcommand检查命令是否已经存在
  2. \newcommand允许您定义可选参数

一般来说,任何\newcommand能做的事情都可以通过来完成\def,但通常需要一些小技巧,除非你想要做一些\newcommand做不到的事情,否则没有必要重新发明轮子。

回答您的具体观点:

  1. 是也不是。使用定义的命令\def必须确切地知道它的选项是什么,以及如何将它们呈现给它。然而,TeX 命令可以有点聪明,它会检查一些东西其他而不是它的参数。处理可选命令的方式是查看流中的下一个字符,如果是,[则调用命令的一个版本,如果不是,则调用另一个版本。因此,如果您准备做一些 hacking,那么可以通过 获得可选参数\def,但它并不像 那样容易\newcommand
  2. 否。由于\def不检查已定义的命令,因此您可以简单地使用\defagain 重新定义内容。要进行检查,您需要使用\@ifundefined命令(请注意 ampersat ( @) 符号!)。
  3. 不!

关于差异可能还有很多要说的,但我说的已经足够了。

答案2

添加到安德鲁已经有了很好的响应,唯一\def可以做但\newcommand不能做的事情是定义使用括号以外的分隔符的命令。例如,如果您希望能够编写\foo<hello>并将“hello”解释为参数,您可以编写

\def\foo<#1>{...something with #1...}

您还可以使用命令读取输入下一个支架,例如

\def\foobar#1#{\framebox[#1]}
\foobar 47pt {hello}

想要兼具 的可扩展性\def和 的易用性\newcommand,请查看 David Kastrup 的suffix软件包。当您想要为文档定义自定义标记时,它非常方便。

还请查看 LaTeX3 包xparse,它以更结构化和更通用的方式介绍了\newcommand应该如何工作。

答案3

以下是其他答案的要点总结。单击每个答案中的 ▶ 符号可查看更多详细信息。

  • \newcommand是 LaTeX 的一部分;\def是 TeX 的一部分。[]

  • \newcommand如果命令已经定义,则失败;\def否则,则不定义。[]

  • \newcommand提供了一种方便的语法来指定参数的数量,并指定一个(单个)可选参数;\def允许对其参数的形式进行模式匹配,这使其更通用但可读性更差。[]

  • \newcommand无法定义名称以“end”开头的命令;\def可以。[]

  • \newcommand定义“长”命令;\def(除非\long\def使用)定义短命令。(“长”命令的参数可以包括段落分隔符。)[]

答案4

一个细微的差别是你不能定义以 开头的命令end

\documentclass{article}
\pagestyle{empty}

\newcommand\test{}
\newcommand\endtest{}

\begin{document}
  \begin{test}
  \end{test}
\end{document}

结果是

! LaTeX Error: Command \endtest already defined.
               Or name \end... illegal, see p.192 of the manual.

您始终可以使用来实现此目的。但即使使用而不是 ,\newenvironment上述代码也不起作用。\providecommand\newcommand

为什么没有 \provideenvironment?据 Frank Mittelbach 称,这是出于性能考虑——节省内存,20 年前是这样。但现在是\ProvideDocumentEnvironmentxparse封装开始的。另外,

与 LaTeX 2ε 的 \newcommand 及其相关函数不同,\DeclareDocumentCommand 函数不会阻止创建以 \end 开头的名称的函数。

相关内容