\toks 是否需要定义 \g@addto@macro?一般可以避免使用令牌寄存器吗?

\toks 是否需要定义 \g@addto@macro?一般可以避免使用令牌寄存器吗?

在LaTeX2e内核中,有一个有用的宏\g@addto@macro

\long\def\g@addto@macro#1#2{%
  \begingroup
    \toks@\expandafter{#1#2}%
    \xdef#1{\the\toks@}%
  \endgroup}

但是我觉得这个定义比较复杂,为什么不这样定义呢?

\def\g@addto@macro#1#2{%
  \expandafter\gdef\expandafter#1\expandafter{#1#2}} % or \xdef?

\par除了前者允许的之外,我看不出这两种实现之间有任何区别。

我们知道etoolbox包和 LaTeX3 在 eTeX 的帮助下使用了另一种方法:

% etoolbox
\newcommand{\expandonce}[1]{%
  \unexpanded\expandafter{#1}}
\newrobustcmd{\appto}[2]{%
  \ifundef{#1}
    {\edef#1{\unexpanded{#2}}}
    {\edef#1{\expandonce#1\unexpanded{#2}}}}

% LaTeX3
\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} }
\cs_new_protected:Npn \tl_put_right:Nn #1#2
  { \cs_set_nopar:Npx #1 { \exp_not:o #1 \exp_not:n {#2} } }

看起来没什么用:我根本\toks找不到\tex_toks:D, say \toksin的任何用处。那么,我们真的需要寄存器吗?source3\toks


注意:我不是在问有关 LaTeX (2e/3) 内核的问题,\g@addto@macro只是举个例子。这更像是 TeX 中的宏寄存器和标记寄存器之间的比较。

答案1

我会将答案分为两部分:不使用 e-TeX 和使用 e-TeX,后者又细分为几个部分。

如果没有 e-TeX,您确实需要令牌寄存器来控制扩展。 里面\edef是经典的例子,其中

\toks@{\mymacro\myothermacro...}%
\edef\foo{\the\toks@}%

不会扩展我们的宏。当你不知道这里的输入是什么时,这一点尤其必要:如果已知只有一个标记,那么\noexpand就可以了。这同样适用于其他扩展上下文,例如\write

(我在这里假设读者知道这\the\toks@只会扩展到 内部的 toks 的内容\edef,而不会进一步扩展。取决于\mymacroETC。,避免穷举扩张可能至关重要。)

关于为什么使用 toks 而不是简单的链的问题\expandafter,LaTeX2e 源代码泄露了秘密:

% \begin{macro}{\g@addto@macro}
% Globally add to the end of a macro.
% \changes{v0.2a}{1993/11/14}{Made global}
% \changes{v0.2w}{1994/01/31}
%     {Use toks register to avoid `hash' problems}
% \changes{v1.0o}{1995/05/17}
%     {Make long for latex/1522}
% \changes{v1.0w}{1996/12/17}
%     {Use \cs{begingroup} to save making a mathord}
% \changes{v1.0x}{1997/02/05}
%     {missing percent /2402}
%    \begin{macrocode}
\long\def\g@addto@macro#1#2{%
  \begingroup
    \toks@\expandafter{#1#2}%
    \xdef#1{\the\toks@}%
  \endgroup}
%    \end{macrocode}
% \end{macro}

尝试使用\g@addto@macro\foo{\def\baz#1{}}或其他任何包含#不使用 toks 的内容并观察问题:您需要将所有#s 加倍。

使用 e-TeX,\unexpanded原语可用。它的作用类似于 toks,但没有分配,这允许更简单的定义,类似于问题中引用的两个。因此,一般来说,在 e-TeX 可用的情况下,几乎不需要使用 toks:因此,\g@addto@macro我们从 LaTeX3 中删除了整个模块。l3toks

TeX 提供了一些 token 参数(例如\everypar),它们的行为与 toks 非常相似,并且必须以类似的方式处理。对于 LaTeX3,计划是为所有这些参数提供一个类似宏的包装器,因此处理这种不寻常的行为将是内核团队独自完成的工作。


即使在 e-TeX 中,toks 也有一个有用的地方,那就是当你想通过寄存器号引用它们时。使用 toks 的通常方式是

\newtoks\my@toks

然后使用控制序列。但是,您也可以按数字使用 toks

\toks0={tokens}

通常,这不是一个好方法。但是,它不会消耗 TeX 哈希表中的 csname。因此,在一个组中(我们可以确保可以自由使用任何寄存器),按数字使用 toks 可能很有用。Bruno Le Floch 在l3regexLaTeX3 模块中利用了这种方法,因为这避免了无用地大量使用哈希表,并且在这种情况下按数字引用实际上并不是一个坏主意。

相关内容