\if 如何工作?

\if 如何工作?

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等于\ifx

这就是您引用的 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是告诉你它是一个可扩展的宏,所以不会等于任何东西。(实际上是错误的)\showmacro:\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(但它可能是活动字符),则可能有两种情况:

  1. \cs与不可扩展原语(如\hbox)或\chardef\mathchardef\countdef\dimendef\skipdef、标记具有\muskipdef相同的含义\toksdef

  2. 的当前含义\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)分配(这不确定——需要更深入的研究)。

相关内容