我正在阅读这个 TeX 编程教程:
http://pgfplots.sourceforge.net/TeX-programming-notes.pdf
在第二个答案中推荐:我应该从哪里开始 LaTeX 编程?
它说:
\toks<number>
还有 255 个令牌寄存器,可以将其视为特殊的字符串变量。当然,每个宏赋值\def\macro{ content }
也都是某种字符串变量,但令牌寄存器是特殊的:当与\the\toks
number 一起使用时,其内容不会被扩展。这可用于细粒度扩展控制,请参阅下面的第 2.3 节。
但没有使用寄存器的示例\toks
。他的意思是什么:“特殊字符串变量”?对于前两种类型的寄存器,我可以分配以下值:
\count0=12
\dimen0=1.102pt
并打印:
Value1: \the\count0
Value2: \the\dimen0
但我不明白,如何使用\toks
。
答案1
标记寄存器与没有参数的宏非常相似,但是在语法和扩展规则上存在差异。
\toks@
使用for的纯文本和乳胶定义,您可以通过以下方式\toks 0
存储标记abc
\toks@{abc}
或者
\def\tmp{abc}
请注意,宏有一个特定的命令来设置宏(\def
或围绕该命令的包装器,例如\newcommand
),但令牌寄存器只使用寄存器名称后跟均衡文本組。
相反,与仅通过引用其名称来扩展的宏不同,标记寄存器与其他寄存器一样,不可扩展,并且其内容是通过扩展来访问的\the
。
所以
\the\toks@
和
\tmp
每个都扩展为abc
。
除了这些语法差异之外,标记寄存器的扩展与宏还有两个重要区别。
扩展
\edef
和其他仅扩展上下文仅限于一个级别:\def\tmp{aaa} \def\tmpb{xx \tmp} \toks@{xx \tmp} \edef\A{\tmpb} \edef\B{\the\toks@}
现在
\tmpb
和\toks@
包含相同的标记列表xx \tmp
,但\A
由完全扩展的可扩展标记定义,因此具有定义,xx aaa
但返回的标记\the
不会在中进一步扩展,\edef
因此\B
具有定义xx \tmp
第二个区别是,由于令牌寄存器没有参数,因此
#
在定义或扩展寄存器时不需要(也不是)特殊。\toks@{#1}
只是一个由两个标记
#
和组成的列表的标记寄存器1
。
这在 LaTeX 的宏中得到使用\g@addto@macro
。
\g@addto@macro@\foo{abc}
应该添加abc
到当前定义的末尾\foo
。
一个简单的(如果我没记错的话也是原始的)定义可能是
\makeatletter
\gdef\foo{123}
\def\gaA#1#2{%
\expandafter\gdef\expandafter#1\expandafter{#1#2}}
\gaA\foo{abc}
\show\foo
运行正常,并显示定义如下123abc
。但是尝试
\gaA\foo{#}
你会得到
! Illegal parameter number in definition of \foo.
#
然而,我们可以利用toks 寄存器中并不特殊的事实,并且寄存器内容只扩展一次
\long\def\g@addto@macro#1#2{%
\begingroup
\toks@\expandafter{#1#2}%
\xdef#1{\the\toks@}%
\endgroup}
首先,\toks@
寄存器被定义为包含第一个参数中传递的宏的扩展,然后是第二个参数的内容。#
在 toks 赋值中可以安全使用。然后,宏被全局定义为 的扩展,\thetoks
其内容正是 的内容,\toks@
无需进一步扩展,即使它包含#
标记:
\makeatletter
\gdef\foo{123}
\g@addto@macro\foo{abc}
\show\foo
\g@addto@macro\foo{#}
\show\foo
生产
> \foo=macro:
->123abc.
l.7 \show\foo
?
> \foo=macro:
->123abc##.
l.11 \show\foo
其中#
已按预期添加(仅#
添加了一个,加倍##
是使用 的产物\show
)。