创建新的原语

创建新的原语

考虑以下 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

相关内容