![\if 如何工作?](https://linux22.com/image/470324/%5Cif%20%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%EF%BC%9F.png)
TeXbook第209页的定义中\if
说:
除非该控制序列的当前等价物已被 \let 等于非活动字符标记
我是否正确理解,如果我们使用
\let\x=<y>
那么这里,根据定义,“该控制序列的当前等价物”是\x
“非活动字符标记”是<y>
?
为什么定义中使用术语“该控制序列的当前等价物”而不是“该控制序列(可能是活动字符)”,哪个更清楚?
另外,为什么定义要费心说“非活动”?因为如果字符标记<y>
是活动的,它就会被扩展(回想一下,\if
扩展了所有可扩展的标记)。
此外,定义中说的是“字符标记”。但也可以有“空格标记”。因此,为了避免歧义,最好说“除非<token>
a 中的\let
是单个字符 - 即,如果它是(字符代码,类别代码)对”吗?
答案1
该\if
行为可以通过其等价类清楚地描述。有一个等价类,其中包含所有不等于(相等于\let
)字符标记的控制序列。此外,每个字符代码都有自己的等价类,其中包含所有具有相同字符代码的标记(即类别代码无关紧要)以及所有等于这些标记(相等于\let
)的控制序列。
尝试这个:
\let\z=Z
\catcode`Z=13
\def Z{}
\if \noexpand Z\string Z YES\else NO\fi
\if \noexpand Z\z YES\else NO\fi
两种情况都给出了 YES。第一种情况:有两个 token Z,一个带有 catcode 13,另一个带有 catcode 12。第二种情况:token Z 带有 catcode 13,并且控制序列等于带有 catcode 11 的 token Z。
有一个特殊的\let
行为规则:如果\let\cs=A
是 done,其中A
是活动字符,则\cs
不等于此活动字符,而是等于其当前含义。例如,如果A
是宏,则\cs
之后是此宏\let\cs=A
。这样的\cs
是 给出的第一个等价类的元素\if
(即\if\noexpand\cs\hbox
给出 true)。另一方面,如果 活动 的含义A
是非活动字符(由前一个给出\let A=c
)并且\let\cs=A
是 done,则\cs
属于 的等价类,其中c
是。此外,在这种情况下, 活动A
本身不等于\string A
,而是等于其含义c
。
尝试这个:
\catcode`A=13
\def A{macro}
\let\cs=A
\if\noexpand\cs\hbox True\else False\fi % True
\if\noexpand A\hbox True\else False\fi % False
\if\noexpand A\string A True\else False\fi % True
\let A=c
\let\cs=A
\if\noexpand\cs\hbox True\else False\fi % False
\if\noexpand\cs c True\else False\fi % True
\if\noexpand A\string A True\else False \fi % False
\if\noexpand Ac True\else False\fi % True
答案2
为什么定义中使用术语“该控制序列的当前等价物”而不是“该控制序列(可能是活动字符)”,哪个更清楚?
那将意味着完全不同的事情。
\if
旨在比较字符标记,以下标记将被扩展,并且前两个不可扩展标记 a 将进行比较。(如果使用\noexpand
或 e-tex 抑制扩展,则标记实际上可能是可扩展的\unexpanded
)
一般来说,任何非字符标记与\relax
其他非字符标记的比较都相似且相等,但不等于所有字符标记。
例外情况隐式字符标记是已经\let
到达字符标记的控制标记。
所以如果你去
\let\implicitx=x
那么\implicitx
等于\if
x
这就是您引用的 TeX Book 中所指的,控制序列\implicitx
(在测试时\if
)已经\let
到达非活动字符标记x
。
如果你这样做
\let\notimplicittilde=~
then\notimplicittilde
不是隐式字符标记,它只是一个普通的宏 csname,其定义与~
这个纯文本文件
\let\implicitx=x
\show\implicitx
\let\notimplicittilde=~
\show\notimplicittilde
\bye
日志
> \implicitx=the letter x.
l.3 \show\implicitx
?
> \notimplicittilde=macro:
->\penalty \@M \ .
l.6 \show\notimplicittilde
=
?
Where\implicitx
具有\show
含义the letter
,它告诉您它充当 的字符,\if
并充当 的 catcode 11(字母)标记\ifcat
相反,它的含义\notimplicittilde
是告诉你它是一个可扩展的宏,所以不会等于任何东西。(实际上是错误的)\show
macro:
\if
\if\notimplicittide
\if\penalty\@M
答案3
让我们看一下完整的引文:
TeX 将扩展后面的宏,
\if
直到找到两个不可扩展的标记。如果任一标记是控制序列,TeX 会认为它具有字符代码 256 和类别代码 16,除非该控制序列的当前等效项等于\let
非活动字符标记。这样,每个标记都指定一个 (character~code, category code) 对。
我认为 256 和 16 最好是 -1;Knuth 想说的是字符和类别代码无法与“真实”字符的代码相匹配。在 TeX 的源代码中,实际值 256 和 16 是不是使用。还请注意,“是控制序列”必须解释为“是控制序列或活动字符”。
现在更有意义了,不是吗?在 TeXbook 描述的时刻,扩展过程已经结束,输入流以两个不可扩展的标记开始,我们将它们称为 A 和 B。
如果两者都不是控制序列,则它们就是字符,并且比较基于字符代码进行。TeXbook 的说法是,如果 A(或 B)是控制序列\cs
(但它可能是活动字符),则可能有两种情况:
\cs
与不可扩展原语(如\hbox
)或\chardef
、\mathchardef
、\countdef
、\dimendef
、\skipdef
、标记具有\muskipdef
相同的含义\toksdef
;的当前含义
\cs
已由 定义,\let\cs=<char>
其中<char>
是一个非活动字符标记。
情况 2 还包括类似\let\x=a
后面跟着的内容\let\cs=\x
,这与 相同\let\cs=a
。
为什么不是第三种情况,即当 的当前含义\cs
已由 获得\let\cs=~
,且带有~
主动字符时?因为这不可能发生。
请记住,\cs
一开始就是不可扩展的,并且\let\cs=~
赋予与(在分配时)\cs
相同的含义。~
答案4
\ThatControlSequence
用于判断或在测试中是否<ThatActiveCharacter>
被分配成对的简单测试如下。(256,16)
\if
跑步
\show\ThatControlSequence
或者
\show <ThatActiveCharacter>
如果输出为=
,则被(256,16)
分配(这不确定——需要更深入的研究)。