\protect 标记列表

\protect 标记列表

为了防止在扩展上下文中扩展宏,我们可以将宏定义为\protected。我想知道是否有办法对任意标记列表执行相同操作。

那么是否可以定义一个可以像下面这样\protecttoks使用和工作的命令:\protecttoks{<token list>}

  • 在正常执行模式下,它只是插入<token list>令牌流,以便它们可以正常执行。
  • 在扩展模式下,它会扩展为自身,即未扩展的标记列表\protecttoks{<token list>}

这个想法是能够将文字材料插入到标记列表中,但标记列表上完成的扩展的确切次数是事先不知道的。

编辑:也许关于以 LaTeX 为例的评论\protect引起了混淆,我删除了它。关键是定义一些仍然能为 提供正确输出的东西\foo,即使该命令在扩展后中断:

\def\foo{\textcolor{blue}{x}}
\edef\bar{\protecttoks{\foo}}

\edef\bar{\bar}
% more calls here ...
\edef\bar{\bar}
\bar

答案1

借助\protected宏,您可以接近想要的结果。基本思路是先用一个\protected宏,然后接另一个非\protected宏。在\edef(或\write\expanded或...)中\protected,TeX 将跳过该宏,而另一个宏将展开,只留下 (前面是\noexpand)和\unexpanded{<stuff>}。宏应该在其他地方\protected展开,去掉未受保护的宏和一层括号。

基本设置是:

\protected\def\ifsafe#1#2{#2}
\def\elseifunsafe#1{\noexpand\elseifunsafe{\unexpanded{#1}}}

然后使用 as \ifsafe\elseifunsafe{<stuff>}。在 中\edef \ifsafe不展开,并且\elseifunsafe展开 并离开\elseifunsafe{<stuff>},因此您只剩下\ifsafe\elseifunsafe{<stuff>}开始时的 。在其他地方\ifsafe,展开消耗\elseifunsafe和 周围的括号<stuff>

您可以\protecting使用 定义一个宏\def\protecting{\ifsafe\elseifunsafe},但它会在第一个 之后消失\edef,只留下实际的保护机制。

测试文档:

\protected\def\ifsafe#1#2{#2}
\def\elseifunsafe#1{\noexpand\elseifunsafe{\unexpanded{#1}}}

\def\protecting{\ifsafe\elseifunsafe}

\def\tmpa{\protecting{\something undefined}}\show\tmpa
\edef\tmpa{\tmpa 1}\show\tmpa
\edef\tmpa{\tmpa 2}\show\tmpa
\edef\tmpa{\tmpa 3}\show\tmpa

\tt
\detokenize\expandafter{\tmpa}\par
\detokenize\expandafter\expandafter\expandafter{\tmpa}
\bye

在终端中打印:

> \tmpa=macro:
->\protecting {\something undefined}.
l.8 ...protecting{\something undefined}}\show\tmpa

?
> \tmpa=macro:
->\ifsafe \elseifunsafe {\something undefined}1.
l.9 \edef\tmpa{\tmpa 1}\show\tmpa

?
> \tmpa=macro:
->\ifsafe \elseifunsafe {\something undefined}12.
l.10 \edef\tmpa{\tmpa 2}\show\tmpa

?
> \tmpa=macro:
->\ifsafe \elseifunsafe {\something undefined}123.
l.11 \edef\tmpa{\tmpa 3}\show\tmpa

?

相关内容