宏的文本在保存到内存之前会经历哪些转换?

宏的文本在保存到内存之前会经历哪些转换?

我注意到 TeX 并不总是将宏的文本保存为输入的内容。例如,以下纯 TeX 手稿:

\def\a#1{\relax#1}%
\font\myfont=cmtt12\myfont%
\meaning\a%
\bye

产生输出

宏:#1->\relax #1

请注意,输出显示“\relax”和“#1”之间有一个空格,而手稿中没有这个空格。这种差异会对手稿的执行产生巨大影响。

例如,请考虑下面的手稿。

\def\a#1{\def\b#1{Hello, world!}}%
\a c%
\bc%
\bye

如果\a的文本按原样保存,则此手稿将成功编译,第二行将定义宏\bc,第三行将输出:Hello, world!。相反,编译会中止并显示以下错误:

! Undefined control sequence.
l.3 \bc

因此有必要知道:宏文本在保存到内存之前究竟经历了哪些转换?

答案1

基本上:TeX 存储的不是文本(字符序列),而是标记:\def它会记住的定义\a具有控制序列\relax,后跟宏参数 1,当您要求打印此标记列表时,它节目\relax为了清楚起见,请在标记后添加一个空格。

我不确定“用户”级别的描述是否正确,TeXbook等等,但我可以指出“内部”表示,如TeX:程序。请参阅 的第 20 部分(标记列表)texdoc tex。标记可以是一(command code, character)对,也可以是控制序列。根据以下背景:

  • 你输入的内容\def将被存储为一系列标记:

第1部分

  • 然后,当您要求\mac显示定义时,上述标记列表将显示为:

第2部分

(在这个例子中,文本恰好是相同的,但请注意,您可以\b在输入文本中省略后面的空格,并且内部标记列表表示将是相同的,因此\b如果您要求打印它,后面仍然会有一个空格。)

答案2

代码

\def\a#1{\def\b#1{Hello, world!}}%
\a c%
\bc%

用一个参数定义\a;调用时\a c#1变为c,因此执行的是

\def•\b•c•{•H•e•l•l•o•,• •w•o•r•l•d•!•}

\b用参数文本c和替换文本进行定义Hello, world!。(这里用来分隔标记,以便更清晰。)

如果你这样做\show\a,你会得到

> \a=macro:
#1->\def \b #1{Hello, world!}.

它使用了不同的表示形式(控制字后有一个空格),但这完全等同于同样的事情:\b已经被标记化。如果你想定义\bc,你需要

\def\a#1{\expandafter\def\csname b#1\endcsname{Hello, world!}}

现在\a c将定义\bc有替换文本Hello, world!


如前所述\show\meaning表示法在控制字后添加了一个空格,如果您复制并粘贴显示的代码,则这无关紧要,因为该位置的空格会被忽略。这样您就可以划分为 token。当然,如果做了一些奇怪的事情,可能会被误导:

\catcode`z=12
\def\a#1{\def\z#1{Hello, world!}}
\show\a

将显示

> \a=macro:
#1->\def \z#1{Hello, world!}.

\a c不是定义一个宏\zc,因为#1仍然是一个单独的参数标记

\def在转换过程中,除了标记化(顺便说一下,它修复了类别代码)之外,对标记进行的任何转换都不会进行。

构成宏名称的字符的类别代码不会以任何方式记录。但是,TeX 只会在控制字后而不是控制符号后在\show/表示中添加空格。因此,如果您添加\meaning

\catcode`z=11
\show\a

对于上面的代码,第二个\show将输出

> \a=macro:
#1->\def \z #1{Hello, world!}.

因为此时,\z应被视为控制字。这更多地与来自文件的输入有关.tex,而不是与标记有关:始终记住,已存储的标记不会受到类别代码更改的影响,但输入的标记会受到影响。

现实世界中的例子是 LaTeX 宏\@。在 的类别代码为 11 的代码中@(通常用于定义“私有”宏),\@仍然具有与 相同的定义@类别代码为 12 时相同。但是,当使用 \@在代码中,因为

\@x

在正常情况下(的 catcode 为 12)被读入为两个标记@,但是当的 catcode 为@11 时,只读入一个标记。这不是什么大问题,但需要注意。

相关内容