为什么在 \protected@write 中将 \thepage 设置为 \relax?

为什么在 \protected@write 中将 \thepage 设置为 \relax?

在内核中 的定义包括到 protected@write的设置。为什么会这样?还有其他方法可以确保不扩展吗?\thepage\relaxthepage

\long\def \protected@write#1#2#3{%
     \begingroup
     \let\thepage\relax
     #2%
     \let\protect\@unexpandable@protect
     \edef\reserved@a{\write#1{#3}}%
     \reserved@a
     \endgroup
     \if@nobreak\ifvmode\nobreak\fi\fi
    }

答案1

这是一个很棒的技巧不是吗:-)

直到页面在输出例程中输出后才会\write发生(事实并非如此\immediate),因此您需要对\edef大多数宏进行扩展,以便它们在您知道它们已定义时进行扩展,否则本地环境可能会结束,参数中的所有宏都变为未定义,并且在期间您会收到未定义的命令错误\shipout。但使用延迟写入的主要原因是,交叉引用等的页码会以正确的数字写出,而正确的数字只有在时才为人所知,因此\shipout您不希望它过早扩展。因此,首先执行\edef设置\thepage为的设置\relax,这样它就不会扩展,然后\write该结果\thepage 可以在输出例程的稍后部分进行扩展。

答案2

如果在期间扩大\edef\reserved@a,它可以有错误的页码。相反,它以未展开的形式传递到 中\write,这将在下一次 shipout 操作期间执行,在那里它将扩展为正确的值。那时对 的重新定义\relax将被遗忘。

当控制序列等效于操作\relax中其保持不变时\edef(对于任何不可扩展的标记也是如此)。

相关内容