我想知道是否有一个很好的通用方法来终止号码它作为宏参数显式给出(作为数字)或隐式给出(作为寄存器值或\chardef
)。这适用于宏内部的条件,例如\ifodd
,\ifnum
或\ifcase
。
最小示例:
\def\mymacro#1{%
\ifcase#1
first\or
second\else
other\fi}
我希望#1
是任何有效的数字或数字表示,例如:(
123
\count@
\myval
给定\chardef\myval=1
),
\2
(给定\def\2{2}
),甚至`\A
。
我知道空格会终止一个明确的数字值,但对于其他输入,空格可能会出现在“first”前面。我试过\relax
,例如\ifcase#1\relax
,但当然,\relax
对于某些输入,then 会出现在“first”前面。用百分号字符终止行并没有多大帮助,或者不是一个通用的解决方案,因为如果第一个真条件是数字而不是单词“first”,case 语句就会变得混乱。
我想到唯一的通用解决方案就是像这样编写宏:
\def\mymacro#1{%
\ifcase\numexpr#1\relax
...
即使输入包含另一个\numexpr
,上述方法似乎也能起作用,但作为一个不想依赖的纯粹主义者etex
,我总觉得有更好的方法。有什么建议吗?
答案1
使用 etex 您可以使用
\numexpr#1\relax
正如你所说。对于经典的 TeX,我认为除了添加和删除终止符之外,没有其他方法,例如
\def\hmm#1!{}
\def\mymacro#1{%
\expandafter\hmm\ifcase#1%
!zero\or
!one\else
!many%
\fi}
\mymacro{1}
\newcount\ccc \ccc=2
\mymacro\ccc
\mymacro{`a}
\bye
答案2
通过\number
它可以使 TeX 评估任何有效的 (!) TeX-⟨数字⟩-quantity。
因此,如果没有 ε-TeX,您可能可以执行以下操作:
\def\foo#1{#1}% *f*irst (argument) *o*f *o*ne.
\def\mymacro#1{%
\ifcase\expandafter\foo\expandafter{\number#1} %
first\or
second\else
other\fi}%
在通过以下方式评估期间\number
触发\expandafter
,TeX-⟨数字⟩-数量表示为#1
以结束,而结束括号在通过评估完成}
时又被删除。 在通过评估期间,数字已转换为显式 catcode-12(other)-digit-character-tokens 序列,可能带有前导 catcode-12-minus。该数字序列以显式空格标记结束,该空格标记在评估过程中被丢弃\foo
\number
\ifcase
\ifcase
收集形成 TeX- 的标记的过程中被丢弃⟨数字⟩-数量。
当然,来自的标记的扩展#1
需要产生一组形成有效 TeX 的标记。⟨数字⟩— 数量而已,没有别的。
也许不久就会出现这样的问题:我们是否可以测试一组标记是否可以扩展为形成有效 TeX 的东西-⟨数字⟩-数量。
由于一组标记可能形成基于扩展的算法实现,因此,这种测试在其他方面之下需要查明以 TeX 标记形式实现的算法是否完全终止而没有错误消息,其中该算法的执行仅由扩展驱动。
理论上,人们或许可以(?)重新实现 TeX 程序中与 TeX 本身扩展相关的那些方面,并且 - 而不是错误消息 - 返回代表错误代码的标记,并对其进行一些基于扩展的评估。
然而,除其他事项外,人们必须注意,在 TeX 本身中以 TeX 代码实现的 TeX 程序子集不能通过用户输入更改为其他内容。
即使可以做到这一切,也只能解决程序终止时是否出现错误消息的问题,而不会解决程序是否完全终止的问题。
我认为这种并无趣味的理论考虑与实践并不相关。