在 TeXbook 的第 20 章中,Donald Knuth 介绍了 的用法\ifcat
,并给出了一个例子:
例如,
\catcode`[=13 \catcode`]=13 \def[{*}
测试后\ifcat\noexpand[\noexpand]
和\ifcat[*
将为真,但测试\ifcat\noexpand[*
将为假。
我在我的机器(mac,texlive2022)上测试了上述示例,有两个问题:
- 有
! Undefined control sequence.
错误。(编辑:由于我的打字错误,我很抱歉。) - 后面应该有一个控制序列
\def
,那为什么可以写\def[{*}
在这里呢? \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 编译)中得到了true
和false
(按该顺序),并且没有任何Undefined control sequence
错误。
至于问题 2,字符[
被定义为活动字符(catcode 13),因此是 的有效目标\def
,如\def[{anything goes here}
,并且会导致在文档中键入时插入替换文本[
(除非被 覆盖\noexpand
)
进一步思考:在这些条件下会停止扩展,因此第一个测试是比较和\noexpand
的 catcode (均为 13)。我的第二个测试(您的第三个测试)与(一个处于活动状态,另一个不处于活动状态)进行比较。您的第二个测试(不是我的)将(为)的扩展与进行比较,因此为真。[
]
[
*
[
*
*