在 \ifnum ... \fi 构造之后使用 \relax

在 \ifnum ... \fi 构造之后使用 \relax

我正在读马尔科姆·克拉克的简单的 TeX 入门。第 111 页有一个练习,定义一个打印当前时间的宏。我在下面重现了 Clark 的回答:

\newcount\minleft
\newcount\timehour
\def\thetime{\timehour=\time
  \divide\timehour by60 %gives 24 hour part of clock
  \minleft=\timehour
  \multiply\minleft by-60 %
  \advance\minleft by\time    %minutes after hour
  \ifnum\time>720\advance\timehour by-12\fi\relax
  \number\timehour:\ifnum\minleft<10 %
                   0\fi\relax\number\minleft
  \ifnum\time>720~p.m.\else~a.m.\fi}

我的问题是我不知道\relax第 8 行和第 10 行(每个之后)在做什么\fi。当我使用这个宏时,它会按预期打印时间:

晚上 8:51

如果我删除\relax第 8 行,我会得到时间,但缺少小时:

下午 51 点

如果我删除\relax第 10 行(并恢复第\relax8 行),则宏将再次像第一次一样工作:

晚上 8:51

我天真地以为\fi结束该\ifnum块的 会结束 中正在发生的一切的处理\ifnum ... \fi,并且 是否存在并不重要\relax,在任何一个地方。显然事实并非如此,但我不知道第 8 行发生了什么,也不知道为什么\relax 没有在第 10 行似乎是必要的。

在不同的上下文中,作者确实解释说,这\relax是一个“不执行任何操作”的命令(在另一种情况下),它阻止 TeX 处理同一表达式的\relax前后部分。我明白了。但关于之后,他说:\relax\relax\fi

“这\relax可能不是必需的,但有一个总是好的:也许是‘安全 TeX’的一个例子。”

这也许是个好建议,但没有什么启发意义。

我在 tex.se 上找到了以下问题\relax,但我认为它们没有回答我的问题(或者至少我还不够聪明无法弄清楚):

\relax 和 {} 之间有什么区别?

\relax 起什么作用?

\relax 和 % 结束一行的区别

正常 \relax 与冻结 \relax

\relax那么,这个宏实际上在做什么?

答案1

我不了解这本入门书,但我对任何声称具有指导意义但又乐于建议您“以防万一”做某事的书都有点怀疑。总是有原因的;在这种情况下,原因是 TeX 的典型怪癖之一。

问题不在于 ,\ifnum而在于\advance。TeX 以相反贪婪的方式扫描您要前进的量:它会尽可能深入输入流,一路扩展,直到遇到不能成为数字一部分的原始量。然后它将找到的内容作为操作数。以下是表达式

\ifnum\time>720\advance\timehour by-12\fi%\relax
  \number\timehour:

被解析。首先,它检查\time720如果是,则开始执行\advance。它读取-12然后继续阅读。现在,你错过的\fi不是句法:也就是说,它是仍然此时在输入流中,在 TeX 处理 时未被删除\ifnum。并且它是可扩展的。扩展它确实会终止条件,但分支没有任何词汇范围,因此扩展会继续,\fi直到\number\timehour,这是一个可扩展的数量,会变成当前的数字\timehour。然后是:,这是不可扩展的和非数字的,因此扫描停止。

结果是,如果\time > 720,我们前进\timehour的值-12<value of \timehour before advancing>。这个整数被吸收,尽管前进后它基本上被丢弃,因为实际使用的唯一代码片段\timehour已被删除。相反,如果\relax没有注释,因为它是不是可扩展,它会立即终止扩展\fi,而\number\timehour不会被丢弃;由于它是无操作,因此没有其他效果。这解释了为什么在没有它的情况下,小时会从输出中消失,只剩下冒号。

我不认为这是很好的风格。它脱离了\relax它所保护的东西。也许更好的做法是写

\ifnum\time>720\advance\timehour by-12\relax\fi
  \number\timehour:

所以整个短语\advance \timehour by -12\relax是一个单一的操作。您也可以在 后面放一个空格-12,但要小心,不要随意丢弃;TeX 对空格的冷漠态度导致了许多编程故障(就像任何语言特性一样,它使得以口语化而不是严格形式化风格编写代码变得容易)。

相关内容