为什么在命令定义中使用反斜杠?

为什么在命令定义中使用反斜杠?

我想知道 (La)TeX 接口定义命令时使用反斜杠的原因。我知道为什么必须使用反斜杠来调用(扩展)命令(宏),但我不明白为什么在定义中使用它。

在 (La)Tex 中,有很多种方法可以定义命令(忽略命令\let和 LaTeX 3 核心以及可能的其他命令),命令名称以反斜杠开头:

  • TeX: \def\gdef和,\edefxdef可能带有前缀\long
  • LaTeX : \newcommand,,,,都可能有后缀\renewcommandprovidecommandDeclareRobustCommand*
  • etoolbox : \newrobustcommand,,,都可能带有后缀\renewrobustcommandproviderobustcommand*
  • xparse: \DeclareDocumentCommand,,,,,所有可能在参数规范中有\NewDocumentCommand一个\RenewDocumentCommand\ProvideDocumentCommand+

还可以定义没有间隙的命令

  • TeX:(\expandafter\def\csname name \endcsname与上面提到的 TeX 命令类似)
  • etoolbox:(\csdef类似于上面提到的 TeX 命令)

我认为没有反斜杠的定义有明显的优势:

  • 更通用:允许创建动态命名的命令(例如 \csdef{double#1}{#1,#1})
  • 更好的语义:反斜杠意味着使用变量,即扩展它
  • 更短:保存一个字符,不打扰眼睛

问题是:既然默认命令定义似乎更有用,为什么还需要反弹呢?

更详细地说明一下这个问题:显然,与 TeX 的定义相比,etoolbox 的定义具有更短、更清晰的优势。xparse 定义在参数灵活性方面也具有明显的优势。因此,将它们结合起来似乎很自然。如果定义(使用来自\expandnextetextools)如下命令

\NewDocumentCommand{\declare}{mmm}{%
    \expandnext{\DeclareDocumentCommand}{\csname #1\endcsname}{#2}{#3}%
}

一个人会失去什么?让我们假设,newrenewprovide被类似地定义,让我们将局部/全局讨论和第三个论点的可能扩展放在一边,\gdeclare从长远来看,导致\edeclare和。xdeclare

答案1

有几个原因可以解释为什么定义文档命令总是使用命令的控制序列 ( \foo) 而不是控制序列名称 ( foo)。当然,其中一些归结为“你必须问 Leslie Lamport 或 Don Knuth”,因为它遵循 TeX 基础知识。(例如,\newcommand\foo镜子\def\foo\DeclareDocumentCommand\foo镜子\cs_new:Npn \foo。)

首先,要求定义时的‘外观’与使用时的‘外观’相同,具有内在的一致性。

其次,要求 token 是构造函数可以避免对命令名称中通常出现的内容产生混淆。例如,如果你这样做

\declare{foo-bar}...

\foo-bar

后者不起作用(假设标准 LaTeX 类别代码),因为 TeX 会“看到”标记\foo后跟连字符和字母b,ar。这看起来是个有问题的好办法。

第三,目前的设置允许“专家”跳过{...}

\newcommand\foo{definition}

工作原理与

\newcommand{\foo}{definition}

当 TeX 比较“小”时,这一点很重要(我们在那里保存了两个标记),但许多人也发现它更容易阅读。(此外,由于大多数优秀的编辑器对 LaTeX 标记的突出显示方式与“运行文本”不同,因此使用基于标记的方法对许多编辑器来说效果更好。)

与此相关,你必须记住,当前的界面是在 20 世纪 80 年代基于 20 世纪 70 年代末开发的系统设计的。在\csname过去,对标记(单独的字母而不是控制序列)的扩展和存储的额外工作比现在重要得多。

最后,如果你看一下我们想要的 LaTeX3 内容避免在文档界面级别尽可能使用“动态”定义。LaTeX2.09/LaTeX2e 的一个教训是,明确定义的界面是一件好事:鼓励使用动态名称对此没有帮助。

答案2

你可以自由地定义,更简单地说,

\def\NewDocumentCommandName#1{%
  \expandafter\NewDocumentCommand\csname #1\endcsname}

然后说

\NewDocumentCommandName{foo}{mm}{Whatever with #1 and #2}

如果你愿意的话。但这并不比

\NewDocumentCommand{\foo}{mm}{Whatever with #1 and #2}

我没有看到“动态定义命令”的清晰语法。

Unix shell 中保留了变量“定义”和“使用”之间的区别,其中foo=bar赋值并$foo传递值。这样做是有原因的。在我看来,TeX 不是这样,就像在许多其他编程语言中一样。

相关内容