我想知道\etoolbox
它是如何\expandonce
工作的。所以我查了一下它的定义,发现
\unexpanded\expandafter{#1}
但无论我在哪里寻找,我都找不到 的定义\unexpanded
。我试过
texdef -t latex unexpanded -s
返回以下内容:
Source code definition of 'unexpanded' could not be found.
\unexpanded is defined by (La)TeX.
\unexpanded:
\unexpanded
我也尝试过查看文档source2e
,但是那里没有相关内容\unexpanded
。
有人能告诉我在哪里可以找到该文档的正确方向吗?
答案1
\unexpanded
是 ε-TeX 基元。如果你这样做
\documentclass{article}
\begin{document}
\show\unexpanded
\end{document}
你会在日志中看到:
> \unexpanded=\unexpanded.
l.3 \show\unexpanded
这似乎是多余的信息,但实际上告诉你这是一个原始的控制序列。原始信息列在 TeX Book 或TeX 按主题分类但你不会\unexpanded
在那里找到它,因为它是一个 ε-TeX 原语。它被描述为在 e-TeX 手册中, 尽管:
\unexpanded<general text>
。扩展是标记列表
<balanced text>
。[...]
在构建扩展标记列表时,扩展产生的标记不会进一步扩展(这与 TeX 和 ε-TeX 中变量
\unexpanded
扩展产生的标记所表现的行为相同 )。\the<token>
答案2
正如 cgnieder 的出色回答所说,\unexpanded
是 e-TeX 的一个原语,即原始 TeX 语言的扩展。原语没有定义,它们是引擎直接理解的命令。其中一些是可扩展的,也就是说,它们不会到达 TeX 的“胃口”,因为它们的扩展就像宏一样(例如,条件语句也是如此);\unexpanded
是这些宏之一。
它是对 的泛化,在或 的\noexpand
上下文中,具有空扩展,但也使下一个标记对于当前任务而言不可扩展。因此\edef
\write
\def\foo{something}
\def\baz{else}
\edef\x{\foo\noexpand\baz}
相当于
\def\x{something\baz}
使用\unexpanded
它可以防止一个\edef
(或\xdef
)或\write
整个标记列表扩展,而无需将其添加\noexpand
到所有可扩展标记的前面。
由于\unexpanded
遵循模式
\unexpanded <general text>
它有一个有趣的特性。当 TeX 想要扩展它时,它会期待找到一个<general text>
定义为
<filler> { <balanced text> <right brace>
和扩展标记来识别 a<filler>
和最终的{
。 A<filler>
只是\relax
和空间标记的任意序列,它们被忽略。{
是类别代码 1 的显式或隐式标记。
这样做的结果是
\unexpanded\expandafter{\cs}
将导致在启动令牌列表\cs
之前展开,这将{
不是不再扩展。事实上,的定义\expandonce
是
\newcommand{\expandonce}[1]{\unexpanded\expandafter{#1}}
此外\detokenize
(e-TeX 的另一个可扩展原语)具有相同的属性。
请注意<filler>
:在某些情况下,它可能会导致一些意想不到的后果,如下所示让狮子跑来跑去。简洁地