![为什么我们需要 11 个 expandafter 来按正确的顺序扩展 4 个标记?](https://linux22.com/image/233605/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%BB%AC%E9%9C%80%E8%A6%81%2011%20%E4%B8%AA%20expandafter%20%E6%9D%A5%E6%8C%89%E6%AD%A3%E7%A1%AE%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%89%A9%E5%B1%95%204%20%E4%B8%AA%E6%A0%87%E8%AE%B0%EF%BC%9F.png)
在附录 D - Dirty Tricks 中,Knuth 给出了使用命令以正确顺序扩展四个标记的示例eleven
\expandafter
。以下是稍作修改以备明天使用的代码!
\tracingmacros=2 \tracingcommands=2
\def\z{M}
\def\Z{C}
\def\a{\z er}
\def\b{ry }
\def\c{\Z hr}
\def\d{ist}
\def\e{mas}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b\expandafter\c\d \e
\bye
这是纯 TeX,所以您需要使用 pdfTeX 来运行它。为什么我们需要 11 个 expandafters?这种类型的定义是否有经验法则?您需要扩展五个,即,\e
也扩展我方便地分开的五个!
答案1
简短的回答
不要想着 11,而要想着 7+3+1 \expandafter
。要达到\e
,你需要 15+7+3+1 \expandafter
。正如 Ulrich 在他的评论中所说,这些数字是2^4-1
,2^3-1
等等。
什么是\expandafter
?
TeX 基元\expandafter
跳过其后的标记,并扩展下一个标记。由于宏和不带参数,\b
因此代码\c
\d
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b\expandafter\c\d\e
扩展为
\expandafter\expandafter
\expandafter\a
\expandafter\b\c "\d, once expanded" \e
这反过来又
\expandafter\a\b "\c, once expanded" "\d, once expanded" \e
最终屈服
\a "\b, once expanded" "\c, once expanded" "\d, once expanded" \e
根据你的\a
、\b
和定义\c
,你不需要所有这些\expandafter
s,因为这些宏不接受任何参数。事实上,以上内容过于简单:在一般情况下,如果宏确实接受参数,则上面的最后一行看起来有点像
\a \once{\b \once{\c \once{\d \e}}}
where\once
不是 TeX 命令,但应该表示参数被扩展一次,最内层的扩展首先发生,最外层的扩展最后发生。这是一个非常愚蠢的例子:
\def\a#1.{#1}
\def\b#1:{#1.}
\def\c#1,{#1:}
\def\d{Hello world!,}
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b
\expandafter\c\d
\bye
\def
首先,\c
将,
中的 替换Hello world!,
为:
。其次,\b
将 替换:
为.
,最后\a
删除.
。在此示例中,所有\expandafter
s 都是必需的。
2^n-1
\expandafter
做什么?
2^1-1=1
\expandafter
扩展下一个标记之后的内容一次,通过归纳,您很容易看到2^n-1
\expandafter
s 在下一个标记时间之后扩展了内容n
。此外,实现这一点需要n
扩展步骤。让我们从这个角度再次查看您的代码:
前 7 个\expandafter
扩展了后面的内容\a
。其中两个这 3需要扩展步骤来扩展\expandafter
之后的 3 秒\a
;请记住,缺少最后一个扩展步骤。在最后一步之前,\expandafter
之后的 3 秒\a
将内容扩展了\b
2 次。第一次扩展在 之后产生\c \once{\d \e}
,\b
第二次扩展在 之后产生\once{\c \once{\d \e}}
。这完成了对两个 的描述这 3扩展步骤。在第三个这 3,后面的内容\a
最后一次展开。
在 TH 的评论中,3\expandafter
扩展了\csname bar\endcsname
两次,从而得到 的展开式\bar
。另一个重要情况是
\expandafter\def\expandafter\mycommand\expandafter{\somecontrolsequence}
这定义\mycommand
为\somecontrolsequence
,一旦扩大。
另一个愚蠢的例子:
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\b\c
扩展\c
两次,从而扩展为类似
\a\b\twice{\c}
答案2
为了扩展与 TH. 对 Hendrik 的回答的评论相同的主题,当你必须使用长\expandafter
链时,你可以利用像\csname...\endcsname
(或者,在某些情况下,\number
)这样的构造,通过在你想要扩展的标记之后/之前放置正确数量的\expandafter
s 来完全扩展事物,例如
\csname macroone\expandafter\expandafter\expandafter\endcsname\macrotwo
\macroone
将与随后\macrotwo
扩大两次的结果相同。
举一个具体的例子,假设您有\a\b\c\d\e
并且想要扩展\e
三次、\c
两次和\a
、\b
、\d
一次。使用 的\csname...\endcsname
方法,它将是(在这里,我们将扩展的结果存储在\temp
宏中,然后可以清楚地看到扩展了什么;您需要中的\show
三个,因为第一个标记需要两次扩展):\expandafter
\def\temp
\def\a{a}
\def\b{b}
\def\c{\C}\def\C{c}
\def\d{d}
\def\e{\E}\def\E{\ee}\def\ee{e}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\csname a\expandafter\expandafter\expandafter\endcsname
\csname b\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\endcsname
\csname c\expandafter\expandafter\expandafter\endcsname
\csname d\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\endcsname
\e
}
\show\temp
\csname @@end\endcsname\bye % to work with both plain and LaTeX
为了进行比较,这里是带有 s 链的相同版本\expandafter
:
\def\a{a}
\def\b{b}
\def\c{\C}\def\C{c}
\def\d{d}
\def\e{\E}\def\E{\ee}\def\ee{e}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\a
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\b
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\c
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\d
\e
}
\show\temp
\csname @@end\endcsname\bye % to work with both plain and LaTeX