在 LaTeX 内核 ( latex.ltx
) 中,我们看到了一些示例
\ifcase#1\or a\or b\or ...
(\ifcase
没有添加\relax
),但是当我们查看一些软件包时,大多数软件包在 之后添加了此语句\ifcase#1
。所以我的问题是:什么时候需要这样做?
答案1
\ifcase
@wipet 给出的答案解释了如果结果为零,则需要将数字的评估与所使用的材料分开,并解释了为什么“空间”或\relax
可能根据输入而错误。
就 LaTeX 而言:当最初编写 LaTeX 时,每个字节都很重要,因此我们在不需要时会删除任何显式分隔,例如,
\ifcase#1\or
这里零值的情况是空的,告诉\or
TeX 计算的数字已经完成。在以下情况下
\ifcase\@eqcnt
我们知道这\@eqcnt
是一个计数器,因此不需要空格或\relax
(甚至正确)
最后,如果你真的不知道输入数据是什么,那么你必须求助于@wipet 与 David Carlisle 共同找到的解决方案,即
\def\zaprelax#1\relax{#1 }
\ifcase\expandafter\zaprelax\number#1\relax
(latex.ltx
有一种情况,\ifcase\number#1
但这也不能解决一般情况(正如我最初所想的);它只在那里起作用,因为所使用的输入实际上不是完全通用的。换句话说,\hexnumber@
在内核中是完全正确定义的。如果输入是普通的,它就不会起作用0
。)
无论如何,如果您不知道输入是什么,那么仅用结束评估\relax
是错误的,正如@wipet 解释的那样:它正确地停止了评估,但您不知道是否\relax
消失或成为零案例的一部分!
所以如果你
\def\foo#1{\ifcase#1\relax 7\or 8\else9\fi}
的替换文本\foo
可能只是一个数字(7、8 或 9)或者\relax 7
后者的行为与其他情况完全不同。
简而言之,\relax
在包中使用可能是不必要的,但也可能完全是错误的。
答案2
具有\ifcase
语法
\ifcase number zero case\or one\or two\or ...\fi
“数字”必须与“零大小写”分隔开。自然分隔符是空格,但有些“数字”格式中“数字”很紧凑(例如,来自的\countdef
,\chardef
额外的空格占了“零大小写”的一部分)。您可以尝试:
\def\test#1{\ifcase#1 77zero\or one\fi} % note the space before "77zero"
literal:\test{0} % the space is a separator of the number, it disappears
\newcount\tmpnum \tmpnum=0
countdef:\test{\tmpnum} % the space is a part of the zero case, it is printed
\chardef\tmp=0
chardef:\test{\tmp} % the space is a part of the zero case, it is printed
\end
如果您需要每种类型的数字中没有空格,则可以将其用作\relax
数字的分隔符。这样不会打印任何内容。但还有另一个问题:如果宏仅用于扩展目的并且评估零大小写,则 \relax 仍是结果的一部分。
编辑:如何解决各种数字格式的问题,#1
以便不\relax
扩展空格?恕我直言,只有通过 eTeX 原语才有可能\numexpr
:
\def\test#1{\ifcase\numexpr#1\relax 77zero\or 2one\fi}
编辑2:感谢 Frank 和 David,我们(在下面的讨论中)找到了经典 TeX 中数字分隔符的强大解决方案:
\def\zaprelax#1\relax{#1 }
\def\test#1{\ifcase\expandafter\zaprelax\number#1\relax 77zero\or 2one\or two\fi}