为什么在将控制序列写入辅助文件的过程中会对其进行扩展?

为什么在将控制序列写入辅助文件的过程中会对其进行扩展?

我正在研究 LamsTeX,一种旧的 TeX 格式,因为它有一些有趣的宏。我发现了这个文章关于它。在文章中我们可以读到

\bitem \LaTeX\ 中许多刚刚被解决的难题在 \LamSTeX{} 中根本不存在。例如,\LamSTeX{} 中不存在“脆弱”命令,也不用担心长 |\write| 和 |\write| 到辅助文件(如 |.toc| 文件)的意外扩展。任意长的文字模式材料可以拆分到多个页面。

因此,我开始感兴趣,并对 LamsTeX 进行了一些实验。查看.toc自动生成的文件,我发现 LamsTeX 保存所有控制序列而不进行扩展,就像它们都使用 LaTeX 或 OPmac 术语“保护”一样。这让我产生了一个问题:在编写控制序列之前,为什么要对其进行扩展?直接编写而不进行扩展不是更好吗?

我查看了与此论点相关的其他问题,但我找不到这个问题的答案。

答案1

保存到临时文件时通常有四个字段包含有关部分的信息:

  • 控制序列位于所有其他控制序列之前,当使用 再次读取数据时执行\input。在写入过程中不得扩展。

  • 章节等的数量必须立即扩充。

  • 章节的标题。撰写时不应展开。

  • 页码。在 期间必须展开\shipout

LaTeX 将第三个字段管理为:“在 期间扩展它\shipout,但使用\noexpand所谓的健壮命令的扩展”。OPmac 做了类似的事情,只有标记为“受保护”的控制序列才会\relax在 期间被设置\shipout。但还有另一种方法,它绝对不会在 期间扩展章节标题\shipout。例如,可以这样做(需要经典 TeX,不需要 eTeX)。

\newcount\secnum
\newwrite\outfile
...
\def\meaninga#1{\expandafter\meaningb\meaning#1\relax}
\def\meaningb#1->#2\relax{#2}
\def\sec#1\par{\advance\secnum by1
   \def\tmp{#1}\edef\tmp{\string\secX{\the\secnum}{\meaninga\tmp}}%
   \write\outfile\expandafter{\tmp{\the\pageno}}%
   ...
}

第一个字段\secX在这里受 保护\string。第二个字段在\the\secnum这里在 期间扩展\edef\tmp。第三个字段(章节标题)使用原始值保护\meaning,即在\edef\tmp处理时立即被反标记化。第四个字段是\the\pageno,它在 期间扩展\shipout。也许在 LamsTeX 中做了类似的事情(我不知道具体情况)。

当然,如果我们有 eTeX,那么我们可以使用\detokenize原始方法更直接地进行去标记化。而替代的“保护”方法也可以更直接地完成:使用\protected\def

请注意,您不能将其用于\the\toks部分标题的扩展保护,因为这不会进行目录代码更改,并且您无法及时使用,\the\toks因为\shipout一页上可以有多个部分。

相关内容