为什么我们需要 11 个 expandafter 来按正确的顺序扩展 4 个标记?

为什么我们需要 11 个 expandafter 来按正确的顺序扩展 4 个标记?

在附录 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-12^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,你不需要所有这些\expandafters,因为这些宏不接受任何参数。事实上,以上内容过于简单:在一般情况下,如果宏确实接受参数,则上面的最后一行看起来有点像

\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删除.。在此示例中,所有\expandafters 都是必需的。

2^n-1 \expandafter做什么?

2^1-1=1 \expandafter扩展下一个标记之后的内容一次,通过归纳,您很容易看到2^n-1 \expandafters 在下一个标记时间之后扩展了内容n。此外,实现这一点需要n扩展步骤。让我们从这个角度再次查看您的代码:

前 7 个\expandafter扩展了后面的内容\a。其中两个这 3需要扩展步骤来扩展\expandafter之后的 3 秒\a;请记住,缺少最后一个扩展步骤。在最后一步之前,\expandafter之后的 3 秒\a将内容扩展了\b2 次。第一次扩展在 之后产生\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)这样的构造,通过在你想要扩展的标记之后/之前放置正确数量的\expandafters 来完全扩展事物,例如

\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

相关内容