为什么 LaTeX 这么复杂?

为什么 LaTeX 这么复杂?

近 10 年来,我几乎每天都在专业上使用 LaTeX,因此我认为我可以说,到目前为止,我或多或少知道自己在做什么。我还使用 C++ 和 Visual Basic 等传统语言进行了很多普通的计算机编程。当我将 LaTeX 与其他语言进行比较时,我经常会想到以下问题:

为什么 LaTeX 如此复杂?

尽管我使用 LaTeX 的经验相当丰富,但我仍然经常遇到不明显的行为和奇怪的错误消息,而且该语言的许多部分看起来晦涩难懂。以下只是几个例子:

  • 宏地狱:除了最简单的宏外,所有宏中都充斥着乱七八糟的垃圾(、、、、、\relax... )\csname\let\patchcmd\expandafter
  • 荒谬\makeatletter\makeatother无处不在
  • 非本地错误消息可能难以修复
  • 没有具有普通操作函数的简单类型(int、bool、float)。相反,不同类型的计数器和寄存器拼凑而成,每个计数器和寄存器都必须以自己的特殊方式进行操作(有时2\mynum,有时2*\mynum,有时\multiply \pgf@x by 2,有时\addtolength{\mynum}{3},...)
  • 循环和条件比它们应该的要复杂得多
  • 没有数组
  • 检查平等性非常尴尬(\equal{\mybool}{true},......)
  • 没有简单的子程序语法
  • 固定内存限制而不是动态分配的寄存器
  • 大多数 LaTeX 引擎中没有增量编译 - 如果我更改了文档的最后一行,或者对 TikZ 图形做了微小的更改,我不必花费数十秒重新编译才能看到效果

我还可以继续。

让我明确一点:我非常尊重那些开发 TeX 及其相关程序和软件包的人。该系统令人印象深刻,功能强大。此外,我上面提到的每一个看似神秘的功能当然存在是有原因的,并且(至少)在设计时,以(至少是局部)合理的方式解决了实际问题。当然,其他编程语言也有缺陷。

但当然,我们仍然有必要认识到目前整个系统的复杂性和局限性,并提出以下问题:一定要这样吗?如果我们能够从头开始设计一个排版系统,那么在 2015 年,我们能不能做出点什么很多更简单、更直观?

答案1

尽管这个问题(和这个答案)会引起意见而不是事实,并因此被传送到版主的遗忘中,但我还是要提出一些想法:

  • TeX 是很古老。它是在 (a) 周围没有足够的 CPU 能力,以及 (b) 它基本上要做的就是生成一些要打印的东西时编写的。但现在它已经成为一把锤子,让一切看起来像钉子(有效或无效):不同的输出格式(例如 PDF、HTML);动画;电子书;幻灯片等等。

  • 一直以来都存在一个严重的问题 —— “你不得破坏遗留文件” —— 在我看来,这阻碍了“清理”语言的可能方法。

  • 和所有编程语言一样,它经历了我所说的生物衰退:新用户从老用户那里学到坏习惯。即使在 TeX.SE 上,也可以看到“正确答案”被冷落,而“仅仅有用的答案”却被接受。

话虽如此,地平线上出现了曙光。我相信 LaTeX3 项目正朝着正确的方向前进,以确保我们最终用户(“作者”)看到的宏地狱和 expandafter 炼狱比迄今为止必要的少得多。所以:

  • 以任何方式支持 LaTeX3 项目;

  • 仔细考虑一下 LaTeX 是否是适合您特定时代的特定文档的载体;

  • 在 TeX.SE 上,当两个答案都有效时,优先选择较简单的那个。

答案2

我认为我可以尝试一下而不带任何偏见,因为我既是一个相当 OKish TeX 用户(绝对不如 TeXpertise),但我仍然认为对于那些没有积极参与开发或在这里或其他地方使用宏操作回答的人来说,这很困难。

我可能会将你的问题改写为,

为什么我们需要如此频繁地深入研究 TeX 的核心?为什么用 TeX 设计一个一致的前端如此困难?

据我帮助过的人的经验来看,这是因为有三个主要原因和几个次要原因。

  1. TeX 作为一种语言很奇怪。这是不得不说的。然而,这种奇怪在很大程度上源于它是一种深奥的语言或晦涩难懂。没有一种面向对象语言既像 TeX 又很流行。

  2. 人们不习惯移动参数(就 Dijkstra 对GOTO语句的抱怨而言)。也就是说,可扩展的控制序列对程序员来说是一个谜,直到它真正扩展到它所包含的惊喜。这使得学习 TeX 的基础知识变得非常困难。即使要打印控制序列包含的内容,您也需要在适当的位置使用\expandafters 和\shows。因此调试非常困难。这对新手来说是一个大问题。

  3. 这可能是最相关的原因:互联网上充斥着关于 TeX 的相互矛盾或过时的教程。没有连贯的方法来做某事。有些人提供更接近金属的纯 TeX 宏解决方案,有些人提供 LaTeX 包解决方案等。这是一个巨大的混乱。不幸的是,这些教程中的许多都来自 90 年代和 00 年代,如果你结合较新的包,你就无法再做太多事情了。此外,正如你所知,随着时间的推移,会出现更好的做法双字母字体样式命令 (\bf,\it,...) 会在 LaTeX 中复活吗?对于数学模式来说,\( 和 \) 是否比美元符号更可取?等等。因此,这只会造成永无止境的混乱。

LaTeX3 项目是解决这些问题的一项重大任务,它将编程和文档级别分开(我非常接近)。希望这能给用户带来一些安心,这样您提到的许多细节就会被扫到编程级别的地毯下。

我认为,如果我们有一本 LaTeX 中级手册,解决这些问题最重要的一步就会相对得到解决。到目前为止,我们要么有能达到现有水平的 Hello World 示例,要么有完全专家级的黑客食谱。没有针对中级的轻度技术手册我可以处理一些@用户。这样就把用户分成了非常不同的

  • 这太疯狂了,我讨厌它
  • 这太疯狂了,我喜欢

组。

答案3

“复杂”——想必每个人都同意 LaTeX 值得拥有这个形容词。

不,我不太同意。我认为使用就我个人而言,我一直认为所见即所得 (WYSIWYG) 风格的编辑界面(我尝试使用过几次)更难使用且不太直观。

如果你想在 latex 中制作一个列表,你找到一个文档并“查看源代码”,然后发现它是

\begin{enumerate}
\item zzzz
\end{enumerate}

所以一旦你习惯了\begin/\end环境概念(这肯定不比 HTML 的<ol>/</ol>元素概念更难),LaTeX 源文件几乎是自文档化的。

现在因为 latex 是开源的调整它可以以各种方式修改,但修改起来可能很复杂这一事实与说它使用起来很复杂是两码事。你的问题中提到了标准编程概念,如数字类型、子程序等。这意味着你应该将 Tex 中的编程功能与(比如说)修改 OpenOffice 的 C++ 源代码进行比较。这是不同的但不一定更复杂,但都比简单地使用系统生成文档要复杂得多。

确实,制作 latex2e 类所需的 tex 编程比理想的情况更复杂,文档也更少,这是 latex3 项目正在尝试解决的问题,但这对大多数 latex 用户影响不大,因为他们只需使用提供的类就可以生成文档。

许多用户几十年来一直愉快地使用 Latex,从未使用过这些

宏地狱:除了最简单的宏外,所有宏中都充斥着乱七八糟的垃圾(\relax、\csname、\let、\patchcmd、\expandafter 等)

类似地,如果您有“\makeatletter 到处都是”,您应该问为什么会有这样的东西,那是一个访问代码的钩子,作者故意让这些代码难以从文档中访问,因此它不是典型的用途,它是系统代码的内联修改,如果这种修改很复杂,那就这样吧。

答案4

如果传统的 LaTeX(更准确地说是 pdfLaTeX)不能满足您的需求,我有两个建议可能更适合您的替代方案:

  • 如果你更像是一个用户而不是一个程序员,并且主要需要几乎每个包都有一个一致的接口,那么可以考虑使用语境而不是 pdfLaTeX。它的用户界面与 (pdf)LaTeX 完全不同,但根据您编写的内容,转换成本可能是值得的。ConTeXt 能够拥有非常一致的界面,部分原因是它是由一小群对界面相关事宜进行严格控制的人开发的。(ConTeXt 格式的最新版本基于 LuaTeX 引擎,因此 LuaTeX 的附加功能会自动累积到 ConTeXt 用户身上。)

  • 如果你倾向于自己编写大量宏,并渴望能够使用类型变量和实际函数(而不是设置“有点”像函数一样的宏...),请考虑从 pdfLaTeX 切换到LuaLaTeX。LuaTeX 是 pdfTeX 的超集,在 pdfLaTeX 下正确编译的文档除了必须应用与输入和字体编码问题以及字体加载过程相关的一些小更改外,在 LuaLaTeX 下也应该可以正确编译。重要的是,LuaTeX 和 LuaLaTeX 将 Lua 整合为一种成熟的脚本语言。特别是如果您熟悉 Lua(或 Ruby 和 Python 等竞争对手)或 C,那么学习如何在 Lua 中编写复杂的函数以及编写与 Lua 端代码交互的简单 TeX 端宏对您来说应该是轻而易举的事。

相关内容