*为什么* TeX 不允许命令名称中包含数字?

*为什么* TeX 不允许命令名称中包含数字?

我不是在问 TeX 的语法是如何工作的。我非常清楚,命令名称中只允许使用字母,除了单字符名称和使用 的构造\csname。我只是问:为什么Knuth 为何做出这种奇怪的选择?在几乎所有其他编程语言中,我都可以调用命令f1f2变量var1var2。但在 TeX 中,我不能。为什么?这种选择的预期好处是什么?

我知道如果如果命令名称中允许使用数字,那么语法就必须在某些地方进行调整,例如,我必须写成\kern 5pt而不是\kern5pt。但是,嘿,我实际上更喜欢前者而不是后者,所以这几乎不是什么大问题。

答案1

我们可以给出一个非常具体的答案:PDP-10 有 36 位字。


首先,请注意 TeX允许在“命令”中使用数字,TeX 的控制序列有两种:

  • 反斜杠后跟一串字母,例如\TeX(遇到非字母时控制序列结束),或
  • 反斜杠后跟一个非字母,如\,\!\\(控制序列在该非字母后结束)。

虽然这里的许多人指出,通过改变“字母”的定义(将字符 0-9 分配给类别代码 11),可以使数字 0-9 也属于第一种控制序列,但也请注意,即使使用默认的类别代码,TeX 也允许十个控制序列\0 \1...... \9(“单个非字母”类型)。

例如,参见源代码TeXbook(搜索The following ``rulers'' have been typeset...),其中 Knuth 定义了宏\1、、、和,并且再次在他定义、、的地方附近使用它们\2,如下所示...\3\4\8Inserting spaces according to the table\0\1\2\3Ord\2Bin\2Ord\3Rel

(因此,如果按照您的建议更改语法,则要么\2Bin不再意味着控制序列“\2”后跟“Bin”,要么必须添加一些特殊的附加规则,例如包含数字的控制序列不应以数字开头等。并且您在问题中提到不介意写\kern 5pt,不要忘记非常常见的模式,如\fam0或,\box255这些模式都必须重写。)

无论如何,要回答你的问题,你必须记住 TeX 的初始设计是如下进行的:

  1. Knuth 看着 TAOCP Vol 2 的一页(打印的)(排版第二版是整个项目的最初目标)。
  2. 他想到他想输入什么,以便获得该排版输出(并且他也可以轻松实现)。
  3. 他编写了程序来实现这一目标。

因此,TeX 的语法或多或少基于 Knuth 在 1977 年初期对输入惯例的个人偏好,以及当时 SAIL 系统上编程的简易性/可行性限制。评论中指出,Knuth 似乎更喜欢输入不带空格的简短格式(这对他来说很有意义,因为他用铅笔在纸上写书,只在最后用电脑打字)。这个理由足够了(参见上面的例子texbook.tex),但我们也要考虑当时的系统限制。

至于控制序列,最早的“TEX 的初步初步描述”甚至没有反斜杠——参见TEXDR.AFT自 1977 年 5 月起(重印为该文集第 24 章)数字排版)。此时,只有“关键词”,例如eqn。但很快(见TEX.ONE1977 年 7 月起,重印为第 25 章数字排版),他采用了当前的做法,即对控制序列使用转义字符(默认为反斜杠)。这一切都发生在写一行代码之前。

此时,他认为控制序列并不重要/用处不大。他只需要一些易于实现且高效的东西,以适应机器。他实现了一些“足够好”的东西:SAIL TeX(又名 TeX78)手册第 11 章(包含在TeX 和 METAFONT:排版的新方向),即TeXbook,有这些规则(不适用于当前的 TeX!):

摘自 SAIL TeX78 手册第 11 章

这里的重点是“这一事实使 TeX 能够非常有效地处理控制序列;并且 TeX 的实用性不会受到严重影响”

我们可以找出这些规则的原因;如何它允许 TeX 高效地处理控制序列。SAIL 语言在斯坦福人工智能实验室(“SAIL”)使用的计算机上运行,PDP-10(又称 DECsystem-10)机器,具有 36 位字。也就是说,机器的本机整数类型可以存储 [0 … 2^36) 中的任何数字。

请注意,2*26^7 < 2^36 < 26^8。也就是说,如果字母表有 26 个英文字母,那么最多 7 个字母的序列可以组成一个单词(第一个字母也区分大小写),而 8 个或更多字母则无法组成。如果这个字母表还包括 10 个数字,那么字母表的大小将是 (26+10)=36,而由于 36^7 > 2^36,即使长度为 7 的序列也无法组成;必须将不同的控制序列的长度限制为 6,放弃一个字母的长度,只是为了获得像\some14u或 之类的名字的一点好处。

更准确地说,有效的实现方式如下(参见源代码,德克萨斯同步):

控制序列(其中一些是预先声明的)记录在哈希表中,并与其等效含义的关联表一起记录。线性探测(例如 ACP 中的算法 6.4L)用于访问此表 […] 较长控制序列的打包表示,使用六位表示第一个字母(以区分大小写),五位表示每个剩余字母,在单词中左对齐。

甚至在本手册印刷时,这些限制就已经开始放宽:最后的附录 X“TeX 的最新扩展”(以“停止印刷!在印刷本手册之前,TeX 添加了下列功能”) 以(TeX78 手册的最后几句话)结尾:“现在可以完整记住任何长度的控制序列;第 2 章提到的七个字母的截断不再发生”。

当 TeX 在 1980–1982 年间用 Pascal(WEB)重写时,许多限制被取消,但那时系统已被广泛使用并且语法也或多或少地趋于融合;人们仍然认为没有必要允许控制序列混合字母和数字,并打破现有的控制序列用法,如\0\1

他在 42:00 左右谈到了这一点1982 年的这段视频(关于 TeX82 内部细节的系列文章的一部分):

在 SAIL 版本的 TeX 中……字符串的实现效率非常低:我们不想将 SAIL 字符串用于控制序列。相反,我们必须进入动态内存,并占用那里的宝贵空间来存储控制序列的名称。如果有人还记得,我第一次设计 TeX 是在 1977 年,当时我有一些非常奇怪的限制,即控制序列最多只能由五个 [他的意思是七——S] 字母,第一个字母之后不再区分大小写,所有这些都是为了我可以保留一个单独的控制序列表。我最初的想法是,几乎没有人会定义新的控制序列。

[观众笑声]

我起初并没有意识到宏会非常强大......逐渐地我们发现人们实际上想要控制序列,所以我们为它们腾出了空间。

答案2

当然,Knuth 这样做的真正原因只有 Knuth 自己才能回答,但我们可以根据我们所知道的事情进行猜测:

  1. TeX 确定控制序列名称的规则完全基于 catcode,这使得它们更易于描述、实现速度更快且更具可定制性。

    由于 TeX 已经有 16 种不同的 catcode,如果不在标记中的 catcode 字段中添加第五位,数字就无法获得自己的 catcode。(这将是浪费,因为 TeX 不需要 32 个 catcode)因此它只能通过两种方式实现:允许other命令名称中的标记或将数字转换为字母。

    在命令名称中允许other使用标记会非常麻烦,因为您经常会意外地将标点符号添加到命令名称中,因此更严重的版本是将数字变为字母。但是查看教科书源代码或 Knuth 编写的 WEB 文件表明,他似乎喜欢将\0to\9作为控制序列的短名称,而这些短名称不需要以空格结尾。

  2. 与上一点类似,似乎还有一个更根本的原因:你写

    但是嘿,实际上我更喜欢前者而不是后者,所以这几乎不是什么大问题。

    但 Knuth 的所有代码似乎都表明他的想法恰恰相反:他似乎总是喜欢没有空格的较短形式。因此,虽然允许在控件名称中使用数字可能对,这似乎与Knuth 的喜欢的风格。

答案3

由于 TeX 创建时内存非常有限,因此简单性是首要考虑因素。如果要让数字用于多种用途,则需要编写更多代码,而好处却微乎其微。

(这原本是作为评论发布的,但由于似乎存在一些共识,因此我将对其进行扩展。)

\catcode如果数字被替换为字母,则需要以其他方式完成的任务:

  • 随后对任何\catcodes 进行更改;
  • 任何算术运算,包括递增计数器;
  • 指定或重置任何尺寸,包括用于重新定位字形、文本块或其他对象的尺寸。

毫无疑问还有更多,但仅凭这些就会破坏识别数字及其最适当用途的简单性。

附录:

必须记住,创建 TeX 的目的是为了能够排版计算机编程艺术(TAOCP)以与该系列原始卷所展示的高质量标准一致的方式进行,这些标准通过 Monotype 最有效地设定。TeX 的设计和实现实现了这一目标。直到后来,Knuth 才被说服将该软件提供给其他人,在这样做的过程中,他接受了扩展 TeX 功能而不损害其原始目的或效率的建议。最后一次(也是最广泛的)此类扩展是 1989 年包含本地重音字母(基本上是 Latin-1),标志着 3.0 版。

Knuth 在他的TeX 网页不会进行额外的扩展,尽管任何人都可以选择进行此类扩展,但生成的程序应该使用不同于“TeX”的名称;该名称仍为 Knuth 自己的作品保留。

答案4

在 TeXbook 中,我找不到 Knuth 选择默认只允许字母的原因。不过,他确实承认可能需要更灵活的控制序列,并指出这可以通过 来实现\catcode

请参阅第 11 页的以下练习,答案在第 301 页(第 911-921 行)。TeXbook 源):

在此处输入图片描述

在此处输入图片描述

相关内容