这也许是一个比较容易回答的问题,而且我意识到它可能会被关闭,但我们还是开始吧......
我目前正在研究 Tex/Latex 的内部结构,发现学习难度相当大。我一直在思考宏系统的数学性质,想知道它与文档的实际排版和布局有何关系。
为了回答我的问题,下面是我对此的简要分析为什么Tex/Latex 真是……无情。这不是为了咆哮,如果觉得是咆哮,请忍耐一下。我会引用那些可能显得咆哮的部分,这样如果你觉得这是旧闻,你可以略读一下。
Tex 是我所说的积极命令语言,但它旨在以声明性的方式使用。您可以使用部分、标题等“标记”您的文档,其方式表面上类似于 HTML。但是,如果您想编写自己的宏来调整任何内容,您必须处理大量复杂的实现细节。
解析 tex 的核心逻辑似乎是“检查下一个标记,执行它要做的事情(这可能会任意改变执行环境中的几乎所有内容),然后使用它并转到下一个标记”。这看起来很简单,但任何标记的操作都可能产生深远的影响在其直接使用范围内并不明显。这与其他命令式语言(如 C++)的传统观点形成了鲜明对比,在这些语言中,良好的设计是“不要使用全局变量,变量应该
const
尽可能多,使用 RAII 建立不变量,并尽可能使函数幂等”。这些做法使函数更容易理解,因为它们使函数更容易理解。易于组合。Tex/Latex 函数不易组合。幽灵般的超距作用和宏之间的不受限制的干扰似乎是惯用的。它比我见过的几乎所有其他语言都更像一台原始的图灵机。它无疑是最脆弱的我曾经使用过的语言。
我觉得这种情况因以下事实而加剧:尽管编写和使用具有高度非局部效果的宏是正常的,但矛盾的是,核心语言本身并不能使自己轻松检查或控制其本地环境以外的环境。因此,我们陷入了混乱
\expandafter
,涉及多种定义宏的方式,我称之为类型系统的东西,等等。
在我看来,Tex 就是这样的。那又怎么样——耸耸肩,对吧?语言就是这样的。
事情是,到目前为止,我所看到的宏系统设计似乎与排版和布局没有任何关系。
我不知道排版和布局到底是什么,也不知道它是如何工作的。这是我的问题:排版和布局算法是否实际上需要宏语言所提供的那种代码转换,或者是否可以通过完全不同的东西轻松实现相同的排版和布局过程?
我说“易于实现”,因为,当然,图灵完备意味着它当然可能的在其他任何语言中都能得到相同的结果。这不是重点。例如,有些语言可以轻松处理矩阵,有些语言可以轻松处理图形,有些语言可以轻松处理字符串,有些语言可以轻松处理谓词等。看待我的问题的一种方式是:Tex 宏系统真的和排版布局的数学和逻辑有着密切的联系吗?
答案1
也许了解一下 TeX 的历史可以帮助回答这个问题。
正如 Knuth 曾经说过的(《数字排版》,第 648 页):
从某种意义上说,我加入 TeX 的许多编程功能都是在经历了一番挣扎之后才加入的
因此,我们可以得出结论,在 Knuth 最初的设计中,排版或布局算法不需要大多数编程功能。Knuth 继续说道:
我知道 Leslie [Lamport] 是如何编写 LaTeX 的——首先,他会用高级编程语言编写算法……然后他会几乎机械地将高级代码转换为 TeX 宏。如果我怀疑这种风格将成为 TeX 最常见的用途,那么我现在可能会非常担心效率问题。
(另见 Lamport 的一篇早期文章 拖船。
Knuth 关于所需宏系统的初步想法可以在《数字排版》第 24 章和第 25 章中找到(或者在其索引中查找条目“\TeX 中的宏,历史”)。例如,他写道:
我曾想过在 TEX 中添加一个解释系统和一种小型编程语言,以便更容易进行此类扩展而不必深入 TEX 的内部,但经过重新考虑,似乎最好假设 TEX 的代码足够干净,以便最好使用 SAIL 代码进行扩展。
如果宏系统由放置在大家庭由 David Bausum 编写,除 \begingroup/\endgroup、\def/\edef/\gdef、\global/\long/\outer 和 \relax 外,其他所有命令均在初始设计后添加。文件 errorlog.tex(参见 加拿大运输安全局)显示了特征的编码日期:
- \afterassignment(1983 年 5 月 27 日添加),
- \aftergroup(1983 年 7 月 16 日添加),
- \csname/\endcsname(1982 年 11 月 13 日添加),
- \expandafter(1982 年 9 月 12 日添加),
- \futurelet(1982 年 12 月 2 日添加),
- \globaldefs(1983 年 1 月 20 日添加),
- \let(1980 年 3 月 26 日添加;因此这是原始 TeX82 的一部分),
- \noexpand(1983 年 5 月 25 日),
- \the(1983 年 7 月 12 日延长),以及
- \xdef(1978 年 11 月 28 日添加;再次成为 TeX82 的一部分)。
几个 if 测试逻辑系列 还有一些是在后期添加的,例如,
- \ifeof(1982 年 9 月 12 日添加),
- \iffalse(1983 年 2 月 3 日添加),
- \ifhbox(1983 年 8 月 27 日添加),
- \iftrue(1983 年 2 月 3 日添加),
- \ifvbox(1983 年 8 月 27 日添加),以及
- \ifx(1981 年 7 月 13 日添加;从一开始就在 TeX82 中为人所知)。
TeX82 的设计中还有很多其他东西没有提供,例如 token 寄存器。但即使没有这些命令,TeX 原语的数量(即 TeX 程序实现的命令)也大约有 300 个,因此与 C 等编程语言相比,排版任务是一项挑战。这套庞大的原语命令对于使 TeX 成为一种灵活的排版语言是必不可少的。TeX 的排版模型盒胶惩罚(在第 3 章中描述)数字排版(即问题后的评论中提到的 Knuth 和 Plass 的论文)最多需要宏系统的几个方面来排版文本:将原语与高级命令相结合的定义和一些测试,例如 catcodes、模式等,以使 TeX 成为一种可用的排版语言。
其他系统(非基于 TeX 的)也实现了换行算法(参见第 105 页左栏)。 访谈:Donald E. Knuth)。因此,此过程不需要 TeX 的宏系统。但您可能需要缩进、对齐、单词间空格、连字、连字符……
请不要指望现在就理解这些乱七八糟的东西,TEX 真的非常简单;相信我。---
Donald E. Knuth,《数字排版》,第 512 页
答案2
在不使用任何 tex 宏的情况下使用 luatex 的接口在多个地方进行了讨论,特别是
http://wiki.luatex.org/index.php?title=TeX_without_TeX
但是你的问题有点模糊。你问的是宏系统是否与布局有密切的关系。文档布局的不同部分由不同的事物实现。
例如,数学由核心引擎代码处理,因此在基本中\[...\]
不需要任何复杂的宏,但是使用的对齐和数字放置逻辑align
主要使用 tex 宏来实现(对\halign
.
类似地,latex 图形放置算法完全在 tex 宏层中实现。当然它不有是,并且在在 tug2016Frank 发表了一个演讲,讨论了在 Lua 中实现的另一种浮点放置算法。然而,当前的浮点放置完全是一个宏层构造。
另一方面,段落换行完全无法通过 TeX 宏控制,事实上 TeX 换行算法现在已经在其他几个系统中使用(包括用于网页的 javascript 版本)。