考虑以下 TeX:
\tt
~~~[def]: \meaning\def \par
~~~[let]: \meaning\let \par
[define]: \meaning\define \par
~[macro]: \meaning\macro
\def\macro#1{some #1 transformation}
\let\define\def
\define\hi{hello,}
\let\let\define
\let\hello{world!}
\vskip 2ex
\centerline{
{\hi}
{\hello}
{\macro{argument-based}}
}
\vskip 2ex
~~~[def]: \meaning\def \par
~~~[let]: \meaning\let \par
[define]: \meaning\define \par
~~~~[hi]: \meaning\hi \par
~[hello]: \meaning\hello \par
~[macro]: \meaning\macro
\bye
产生输出
[def]: \def
[let]: \let
[define]: undefined
[macro]: undefined
hello, world! some argument-based transformation
[def]: \def
[let]: \def
[define]: \def
[hi]: macro:->hello,
[hello]: macro:->world!
[macro]: macro:#1->some #1 transformation
我以为\let
只是复制了那个宏控制序列的定义;这里是否发生了更基本的事情?事实上,我并不指望\let
能够将原始函数的控制序列重定向到其他函数。全部。即使\let
只是创建对定义的新引用,这个相关答案意味着,正如我在 TeX 上下文中理解的那样,基元不应该具有“定义”。基元是否具有在 TeX 中无法表达但仍可引用的“定义”?
还请考虑扩展场景:
\def\def{bad}
\def \par
[def]: \meaning\def \par
[let]: \meaning\let
会产生
bad
macro:->what?
\def
如果\let
按照它所说的去做,那么如何\meaning
获得价值\def
呢?
答案1
当你这样做时\let<token-a>=<token-b>
,TeX 会创建一个指向存储的内存位置的指针<token-b>
。原始数据以 TeX 运行开始时的名称存储,在格式文件加载之前;没有其他方法可以表示它们;也许会primitive \def
更好,但 Knuth 选择不这样做,而是仅用其(原始)名称来表示原始数据。所以如果你这样做
\let\define\def
即使之后重新定义,\show\define
也会输出a 。每当说你知道这是一个原语并且与该原语具有相同的含义。因此,在 LaTeX 中,输出\define=\def
\def
\show<token>
<token>=\xyz
\xyz
<token>
\show\@@input
> \@@input=\input.
如果你
\let\define\def
\let\let\define
你让\let
指向 指向的内存位置相同\define
,即 的原始内存位置\def
。当然,\let
除非你事先用\let\primitivelet\let
(或类似方法)保存了它,否则你就会丢失原语。TeX 遵循以下说明:如果你想搬起石头砸自己的脚,它会很乐意让你这么做。只有一些(不可访问的)标记受到保护,不能被重新定义,因为人们实际上无法访问它们的名称。
实际上,LaTeX3 项目的目标之一是重命名全部原语,以避免用户这样做时出现问题\renewcommand{\box}{something}
:在以新名称保存每个原语后,LaTeX3 代码仅使用这些新名称,而不使用原始名称。
这在宏中不会发生:如果你说
\def\macro{replacement}
\let\newmacro\macro
a\show\newmacro
不会有任何 的踪迹\macro
。事实上,\macro
可以重新定义,而不会改变 的含义\newmacro
。
注意:\let\define\def\show\define
打印\define=\def
并不意味着 TeX 会记住\def
是什么,万一 也打印\define\def{Oops}
。 后面的=
符号\def
只是表示含义,而不是实际命令。pdftex
但是,可以通过在 的名称前加上 来访问原语\primitive
。 因此,将独立于 的任何重新定义\primitive\input
执行 的原语含义。\input
\input
请注意,\meaning
和\show
在这方面是相同的;不同之处在于\show
中断 TeX 运行并在终端上显示含义,而\meaning
只是打印它(从技术上讲,它通过类别代码 12 的字符来表示含义,10 表示空格)。
答案2
egreg 的回答当然是正确的,但可能有点简洁。一个说明性示例可能会有所帮助。
\let\let\futurelet
\let\def\let\xdef\futurelet\gdef\xdef\futurelet{}
\immediate\write20{\string\let=\meaning\let}
\immediate\write20{\string\futurelet=\meaning\futurelet}
\immediate\write20{\string\def=\meaning\def}
\immediate\write20{\string\gdef=\meaning\gdef}
\immediate\write20{\string\xdef=\meaning\xdef}
\bye
生产
\let=\futurelet
\futurelet=macro:->
\def=\xdef
\gdef=\futurelet
\xdef=\gdef