和
\edef\x{\ifnum0=0\else\fi}
存在\relax
和与
\def\y{\relax}
我们发现这\ifx\x\y
是错误的。为什么?
答案1
让我们看一下与 TeX 交互会话的记录。
> tex
This is TeX, Version 3.1415926 (TeX Live 2011)
**\relax
*\def\x{\relax}
*\edef\y{\ifnum0=0\fi}
*\show\x
> \x=macro:
->\relax .
<*> \show\x
?
*\show\y
> \y=macro:
->\relax .
<*> \show\y
?
*\ifx\x\y\message{EQUAL}\else\message{UNEQUAL}\fi
UNEQUAL
*\edef\z{\ifnum0=0 \fi}
*\show\z
> \z=macro:
->.
<*> \show\z
?
*\bye
No pages of output.
Transcript written on texput.log.
\x
为什么和不等价?而且为什么和首先\y
就不等价?\y
\z
条件语句
\ifnum0=0\fi
或者
\ifnum0=0\else\fi
几乎是相同的,并且\y
变为非空的事实源于 TeX 针对过早扩展采取的另一项预防措施。
当 TeX 寻找 a 时,<number>
它会在过程中扩展 token。但在这种情况下,它会找到 a\fi
或 an\else
与 the 匹配,\ifnum
而搜索要测试的第二个数字仍然是未完成。如果它扩大了,\fi
否则\else
一切都可能不好。因此,在这种情况下,TeX 会插入一个“安全”标记,它在终端上表示为\relax
但实际上不是我们知道并被允许使用的相同\relax
。例如,您不能重新定义此标记:
This is TeX, Version 3.1415926 (TeX Live 2011)
**\relax
*\edef\x{\ifnum0=0\fi}
*\expandafter\def\x{Something}
! Missing control sequence inserted.
<inserted text>
\inaccessible
<*> \expandafter\def\x
{Something}
\def
从上面的交互式会话中可以明显看出,不允许将“冻结放松”令牌喂给。
问题没有显示
\edef\z{\ifnum0=0 \fi}
因为查找以<number>
空格标记终止(然后被忽略)。因此,这只是一种复杂的说法
\def\z{}
注意。使用\edef\Z{\ifnum0=1\else\fi}
或\edef\Z{\ifnum0=1\fi}
的扩展\Z
将为空,因为“冻结放松”标记成为“真实分支”的一部分,因此它消失了。
TeX 何时插入“冻结放松”?
TeX 会跟踪条件的嵌套,当在与正在评估的条件相同的级别遇到\else
或时,就会插入冻结的松弛\fi
和本次评估的扩展过程尚未完成。
例如,TeX 在
\ifnum0=1\else\fi
因为 a<number>
是通过扩展以下 token 来收集的。另一种情况是
\if\fi
这会导致空扩展,因为二插入冻结的放松令牌,就其而言,它们是相等的\if
。此外
\if\relax\fi
插入冻结的放松,但再次与冻结的放松标记\if
进行比较\relax
并且测试返回真相。
答案2
用更简单的语言来说,有两个 TeX 扫描规则需要牢记:
1) 的展开式\ifnum...\fi
为空的 a如果测试为假,\relax (frozen)
否则。
true condtion -> \relax (frozen)
false condition -> empty
2) TeX 在读取整数时会一直读取,直到发现不可扩展的内容(例如空格)。
考虑以下 MWE:
\tracingall
\count0=5
\count13=5
\count0=2\ifnum\count0=\count1 3 some words\fi9\par%false->empty
\the\count0 %29
\bye
在这里,我们看到两个规则都在运行,TeX 试图将一个值放入\count0=2
,但继续扫描,直到找到一个不可扩展的标记。它遇到了条件。它评估条件(为假),并根据规则 1)ifnum..\fi
将其清空。然后扫描完成,count0=2{empty}9,因此为 29。
修改 MWE 以完成讨论(\ifnum\count0=\count13)
。
\tracingall
\count0=5
\count13=5
\count0=2\ifnum\count0=\count13 some words\fi9\par% true>\relax prints some words 9
\the\count0 % has the value of 2
\bye
如果在 中有一个条件\edef
,它的行为与扩展其内容的方式完全相同edef
。问题的第二部分源于 TeX 插入的松弛是“冻结的”松弛,并且硬编码到引擎中。(参见https://tex.stackexchange.com/a/57404/963)。
a看来 egreg 和 David Kastrup 称此为空虚,而\relax
an未完成的条件。