TeX/LaTeX 中的\let
和命令有什么区别?\def
最好请提供一个简单的例子来说明它们之间的区别。
答案1
不同之处在于评估“右侧”的时间。
因此\let\foo\bar
定义为\foo
具有\bar
在定义点。另一方面,\def\foo{\bar}
实际上定义为\foo
具有\bar
在使用时。
考虑:
\def\bar{hello}
\let\fooi\bar
\def\fooii{\bar}
\fooi +\fooii
\def\bar{goodbye}
\fooi +\fooii
这产生了
hello+hello
hello+goodbye
这是一个简单的过程。
然而,这也是一个微妙的问题,因此可能值得强调几个关键点:
当 TeX 遇到诸如 之类的控制序列时
\fooi
,它会对其进行评估;如果这些是宏(即,它们已由 定义\def
,或\let
等于 定义的某个东西\def
),那么结果是它们将扩张到其他标记,然后 TeX 将依次检查这些标记,依此类推,直到剩下的是“原始”控制序列或字母(我稍微简化了一点)。\fooi
直接扩展到字符hello
(因为\bar
最初是这样的,并且\fooi
被定义为具有相同的价值)。\fooii
,相反,扩展为\bar
,然后立即重新审查并重新扩展。在第一种情况下,\bar
扩展为hello
,在第二种情况下扩展为goodbye
。的定义\fooii
没有改变,但\bar
在两者之间重新定义了。清楚了解这个递归扩展的过程是非常在学习如何开发和调试 TeX 宏时很有帮助。
答案2
虽然现有的答案都是正确的,但我想强调一点,这一点还没有明确提到。我自己最近从 Joseph Wright 那里得到了这个信息(见他的回答和我们的评论简单地消除一些 LaTeX 内部混淆)。
正如 Michael 所说,\let\macroa\macrob
“复制” 的定义\macrob
到\macroa
。然而,在我看来,这里重要的是,定义实际上并没有被复制,即存在两次,但命令序列\macroa
现在指向同一个哈希表输入为\macrob
。这意味着\let\macroa\macrob
使用更少的内存空间(在早期非常重要,但现在不再重要),并且速度更快,\def\macroa{\macrob}
因为在第二种形式中二命令序列名称必须在哈希表中解析。
也\let
实际上“复制”了代币,它们不必是宏/命令序列。这允许定义表示隐式字符的命令序列,例如\let\bgroup={
。
答案3
它们完全不同。\let
将命令复制到新名称,而\def
创建新命令。
例如:
\def \foo {bar}
创建一个新命令,运行时\foo
进行计算。bar
\let \foo \bar
将命令从\bar
命令复制到\foo
命令,因此您可以调用其中任何一个。因为它是一个副本(而不是从一个到另一个的指针),所以重新定义\foo
不会改变的行为\baz
。因此:
\def \foo {bar}
\let \baz \foo
\baz % Outputs 'bar'
\def \foo {new-definition}
\baz % Still outputs 'bar'