关于 TeXbook 中的 \ifcat 的一个问题

关于 TeXbook 中的 \ifcat 的一个问题

在 TeXbook 的第 20 章中,Donald Knuth 介绍了 的用法\ifcat,并给出了一个例子:

例如, \catcode`[=13 \catcode`]=13 \def[{*} 测试后\ifcat\noexpand[\noexpand]\ifcat[*将为真,但测试\ifcat\noexpand[*将为假。

我在我的机器(mac,texlive2022)上测试了上述示例,有两个问题:

  1. ! Undefined control sequence.错误。(编辑:由于我的打字错误,我很抱歉。)
  2. 后面应该有一个控制序列\def,那为什么可以写\def[{*}在这里呢?
  3. \ifcat[*你能解释一下和之间的区别\ifcat\noexpand[*吗?

答案1

在 TeXbook 中寻找“活跃”的内容揭示了(其中包括)

(第 40 页)练习7.5用 TeX 做实验,看看\string当它后面跟着一个活动字符(如 )时会发生什么~。(活动字符的行为类似于控制序列,但它们没有以转义符为前缀。)

(第 47 页)练习 8.2(d)活动字符后的空格会被忽略吗?

(第 155 页) A\mathcode还可以具有特殊值"8000,这会导致该字符的行为就像它具有 catcode 13(活动)一样。附录 B 使用此功能以稍微棘手的方式'扩展为。^{\prime}

(第 241 页)例如,' ??0.2010' 和 ' ' 的宽度相同,因此它们的小数点将很容易对齐。以下是为此目的297.1???设置 ' 的一种方法:?

\newdimen\digitwidth
\setbox0=\hbox{\rm0}
\digitwidth=\wd0
\catcode‘?=\active
\def?{\kern\digitwidth}

(第 307 页)练习 7.3 的解答7.3. 1、2、3、4、6、7、8、10、11、12、13。活动字符(类型 13)有些特殊;在大多数情况下,它们的行为类似于控制序列(例如,当您说 ' \let\x=~' 或 ' ' 时),但是当它们出现在或\ifx\x~的标记列表中时,以及在或之后未扩展时,它们的行为类似于字符标记。\uppercase\lowercase\if\ifcat

您的问题是关于第 209 页的文本,但我提到其他部分是因为它们有助于阐明这个问题。

首先,您会看到\def?{\kern\digitwidth},主动角色可以跟随\def\let如第 40 页所隐含地告诉其他示例并得到证实。

请注意这句话

\catcode`?=\active
\catcode`?=13
\catcode`\?=\active
\catcode`\?=13

都是等效的方法,以便为?字符分配类别代码 13,因为\chardef\active=13这是在纯 TeX 和 LaTeX 中完成的。

接下来要注意的是\ifcat比较后面两个词法单元的类别代码宏扩展后. 因此

\catcode`[=13
\def[{*}
\ifcat[*

将返回真的, 因为[ 宏及其展开是*。相反,

\ifcat\noexpand[*

将返回错误的,因为\noexpand的扩展在于使下一个标记不可扩展(第一次重新检查),所以 TeX 比较两个标记,一个是类别代码 13,另一个是类别代码 12:第 307 页的示例与此应用程序相关。

让我们看一些我假设的例子

\catcode`[=13 \catcode`]=13

第一个例子

\def[{*}\def]{*}
\ifcat[]

将返回真的,但不是因为角色[]是活跃的。

第二个例子

\def[{*}\def]{a}
\ifcat[]

将返回错误的

第三个例子

\def[{*}\def]{a}
\ifcat\noexpand[\noexpand]

将返回真的


作为附录,我补充了一些关于\uppercase和的可能比较隐晦的段落\lowercase。主要应用如下:

\begingroup\lccode`~=`? \lowercase{\endgroup\def~}{whatever}

它可以起作用并为活动字符分配一个含义?(而无需使其处于活动状态),因为\lowercase会返回\endgroup\def??具有类别代码 13,因为\uppercase永远\lowercase不会改变类别代码,只改变字符代码。

答案2

使用代码

\documentclass{article}

\catcode`[=13
\catcode`]=13
\def[{*}

\begin{document}

\ifcat\noexpand[\noexpand]
true
\else
false
\fi

\ifcat\noexpand[*
true
\else
false
\fi

\end{document}

我在结果文档(用 pdflatex 编译)中得到了truefalse(按该顺序),并且没有任何Undefined control sequence错误。

至于问题 2,字符[被定义为活动字符(catcode 13),因此是 的有效目标\def,如\def[{anything goes here},并且会导致在文档中键入时插入替换文本[(除非被 覆盖\noexpand

进一步思考:在这些条件下会停止扩展,因此第一个测试是比较和\noexpand的 catcode (均为 13)。我的第二个测试(您的第三个测试)与(一个处于活动状态,另一个不处于活动状态)进行比较。您的第二个测试(不是我的)将(为)的扩展与进行比较,因此为真。[][*[**

相关内容