LaTeX 有什么缺点?
这几天重度使用,又经历代码重构,意识到TeX/LaTeX这类系统也是让用户戴着镣铐跳舞。
计算机高级语言权衡了程序的复杂性和计算机硬件的处理能力,一般用上下文无关语言描述,比这个更隐蔽的关联在解析(parsing)之后的语义处理中解决。用上下文无关语言,可以把程序代码的层次关系显现出来,用的基本上是括号嵌套的手段,从而可以形式化地检查程序是否正确。这是让程序员戴着镣铐跳舞。这个方向没有错,更现代的语言甚至给程序员带上更多的镣铐,如静态类型检查。表达精确的、复杂的东西,人比计算机容易出错。计算机汇编语言就不是这样,它也没有手段把代码的层次关系显现化。
自然语言的深层结构号称比上下文无关语言更复杂,但其实表层比正则语言更简单。自然语言同样需要展示层次关系。自然语言用的是“隔断”的手段,把一串记号用一个记号隔开。比如排比句,每个句子用分号隔开。数学的语言也是一种自然语言,因为它并没有经过系统的设计。一个序列 ,各个成员之间用逗号隔开。层次关系并不总是并列的。引语需要用与之前、之后的内容隔开。不过可以用不分左右的直引号。配对的括号也是这种手段的延申,只是括号内的东西与之前、之后的内容用不同的记号隔开。这样就有办法展示一层的层次关系。展示多于一层的层次关系,自然语言包括数学语言用的是不止一种隔断符,比如中文的顿号、逗号、分号,数学的圆括号、方括号、花括号。显然层次的数目也是有限的。认识到要求括号左右配对就可以用一种括号表示无限的层次之后(直的单引号、双引号各自配对,交替嵌套也可以),程序设计语言的需求终于可以被满足,但自然语言包括数学语言并没有接受这个约定,数学上半开半闭区间的写法就很能说明这个问题,它的左边括号和右边括号是圆是方可以不一致。自然语言还有一个展示层次关系的办法是用列表(清单),清单可以按层次用数字、字母、带括号等办法编号。
然而,只有“隔断”是人能靠直觉把握的,括号配对、清单都需要额外用理性检查。证据是高亮配对的括号几乎是程序编辑器的刚需,还有不少程序编辑器甚至支持自动输入成对的括号、引号。还有个常见的场景,会议上脱稿发言,“下面讲三点,第一点是……;第一点可以分为五小点,第一小点是……有四种情况:第一种是……”。极少见能够把点数圆回来的。大多数发言人是第一点、第一小点、第一种情况的无限展开、反复细分(还有递归的,也就是每次细分后都是“第一点”),直到发言被打断。自然语言的分层结构就像C语言的goto一样,是乱跳的,这真是个美妙的对称关系。
TeX设计时其实还是更靠近自然语言的,没有把那么多文稿里的深层结构显现化。但到LaTeX的时代,计算机高级语言已经发展多年,有比较成熟的理论,用户也喜欢用,因此LaTeX一代比一代更结构化,往计算机高级语言靠拢。比如控制字体的命令,TeX的风格是这样:to be {\bf bold} or not (更原始的风格是这样:to be \bf bold \rm or );LaTeX倾向于使用这种:to be \textbf{bold} or not。估计LaTeX的设计者觉得用计算机的栈来帮写作者记住\bf之前的字体格式是减轻了写作者的心智负担吧。更极端的是Typst,是完全按计算机高级语言的写法来。
这种趋势,虽然可以帮助用户在写作阶段梳理清楚层次关系,但是却增加了用户的心智负担。一篇文稿,起源是人的语言表达,终点是呈现给人阅读的页面。这两端都是没有把深层结构显现的。两端之间是写作系统。为了写出能编译通过的源文件,作者要往写作系统额外投入时间精力,投入的时间精力与文稿的篇幅不成比例。写好的源文件要改,比如把节提升为章,把几个小图合成大图,这里碰到的麻烦和软件工程的屎山只有一点区别:你不需要考虑其他项目对这篇文稿的依赖。要让源文件的修改显得没那么麻烦有一个办法:定义宏把分章节、插入图这样的任务包装起来,以后只修改宏的定义。问题在于需要有文稿将如何演变的先见之明。还好,LaTeX的\section{节标题}和节的内容之间没有要求把嵌套关系显现,于是两节合为一节只需要把\section{}删掉。如果它是要求这么标记节的:\Section{节标题}{节的内容},那么两节合为一节还需要仔细检查花括号的匹配。LaTeX里面有很多类似后者的要求,尤其是数学式,这就是我当前不喜欢用它的原因。比如排版分数的命令,我觉得TeX用 $a /over b$就比LaTeX用$\frac{a}{b}$好。更极端点,LaTeX的\item又比HTML的<li></li>好,后者真的不是给人类写的。
如果把文档排版语言排序,按照对用户的心智负担从轻到重,大体如下:
无结构纯文本 < Markdown, AsciiDoc之流 < TeX, LaTeX < Typst < HTML <XML
评估的标准倒是很简单也很形式化,看看语法里面,隔断的手段(比如逗号、分号这样的分隔符,比如分数的\over)和包裹的手段(比如配对的括号,比如XML标记)的比例。我个人是越来越倾向于无心智负担的写作了,不过也不看好Markdown。