我正在閱讀 TeX 程式設計教學:
http://pgfplots.sourceforge.net/TeX-programming-notes.pdf
這裡的第二個答案推薦:我該從哪裡開始 LaTeX 程式設計?
它說:
\toks<number>
還有 255 個令牌暫存器,可以將其視為特殊的字串變數。當然,每個宏賦值\def\macro{ content }
也是某種字串變量,但令牌暫存器很特殊:與 number 一起使用時,它們的內容不會擴展\the\toks
。這可用於細粒度擴展控制,請參閱下面的 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
)。