扩展定律 (\chardef\foo=\foo)

扩展定律 (\chardef\foo=\foo)
  • 事实我的系统上 pdfTeX 编译的 LaTeX 文档的默认字体的文件名是cmr10。 (我怎么知道的?\fontname\font请参阅这里

  • 事实文件中定义的字体cmr10在代码点 3 处有一个希腊大写字母 lambda 的字形,在代码点 31 处有一个表示空集的数学符号的字形。(我怎么知道的?\fonttable{cmr10}请参阅这里

考虑以下 (La)TeX 手稿,灵感来自这个答案

\documentclass{article}
\begin{document}
\def\foo{1}
\chardef\foo=3\foo
\end{document}

使用 pdfTeX 版本 3.14159265-2.6-1.40.18(TeX Live 2017)编译手稿会生成一个 pdf 文件,其正文由一个字母组成:希腊大写字母 lambda。

这与我的预期相反,我认为 pdf 的主体由空集的数学符号组成。

我的期望基于什么?基于 Donald Knuth 的TeXbook,第 20 次修订印刷(Addison-Wesley 1991),其中第 215 页列出了全部可扩展令牌的情况不是扩大。

如果您仔细查看列表,您会注意到,在 的情况下\chardef,宏扩展仅在读取要定义的控制序列的阶段受到抑制。(相比之下,\def在吸收参数文本和替换文本时,扩展也受到抑制。)

回到我开始的手稿,从 Knuth 的不可展开列表中可以推断出,\foo该行中第二次出现的控制序列

\chardef\foo=3\foo

展开。请注意,在进行此展开时,\chardef定义仍在处理中,因此控制序列\foo仍必须定义为具有替换文本的宏1。因此,此行重新定义\foo\char31

有趣的是,以下类似的手稿产生了预期的结果(即空集符号)。

\documentclass{article}
\begin{document}
\def\foo{1}
\chardef\bar=3\foo\bar
\end{document}

答案1

关键是暂时变成\chardef\<name>。我们可以通过 看到这一点:\<name>\relax\tracingall

\def\foo{1}
\tracingall
\chardef\bar=3\foo\bar

产量

{\chardef}
{changing \bar=macro:->\mathaccent "7016\relax }
{into \bar=\relax}

\foo ->1
{changing \bar=\relax}
{into \bar=\char"1F}
{\char"1F}

\def\foo{1}
\tracingall
\chardef\foo=3\foo

我们得到

{\chardef}
{changing \foo=macro:->1}
{into \foo=\relax}
{changing \foo=\relax}
{into \foo=\char"3}
{\char"3}

所以我们得到你观察到的结果,不是因为\chardef未能扩展材料,而是因为材料的性质在检查时

Knuth 说:

\TeX\ takes precautions so that constructions like `|\chardef\cs=10\cs|' and
`|\font\cs=name\cs|' won't expand the second |\cs| until
the assignments are done.

(第 24 章“垂直模式摘要”,第 278 页)。

答案2

引用 TeXbook(第 278 页)

TeX 采取了预防措施,使得诸如 ' \chardef\cs=10\cs|' 和 ' ' 之类的构造在分配完成之前\font\cs=name\cs不会扩展第二个。\cs

这些预防措施在模块 1224 中介绍tex.web

在此处输入图片描述

“简写 def” 是模块中描述的类似定义的原语之一。

克努斯警告说,这本书并不总是讲述完整的事实。

相关内容