为什么 TeX/LaTeX 编程在语法上与其他语言有如此大的不同?

为什么 TeX/LaTeX 编程在语法上与其他语言有如此大的不同?

通常,例如,当我想要一个 if 时,我会做这样的事情:

if(value) {
    ... whatever code ...
}

但在 LaTeX 中,它的:

\ifnum\count0<100
    ... whatever LaTeX-code ...
\fi

例如,没有括号等来表示 if 语句的开始和结束位置。此外,由 LaTeX 检查的 if 条件本身也没有括号等。

当然,这些都是细微的差别,但(根据我的经验)阅读其他语言的源代码比阅读 TeX 文档的源代码要容易得多。当然,这可能是个人原因,因为我使用非 LaTeX 语言编程的次数比使用 LaTeX 的次数多,但我仍然认为强迫用户使用这种语法没有任何好处。

有人能向我解释一下吗?

答案1

TeX 不是常规的编程语言:它是一种“宏扩展语言”。TeX 起源于报纸使用的系统,其中每篇文章都以“来自我们的记者”或“来自我们的金融记者”开头。排版系统当时有一种声明宏的方法\foc,或者\fofc可以用这种固定的文本替换宏。

现在想象一下,一个宏可以有一个参数:\foc{special},扩展为“来自我们的特别通讯员”。因此:宏加上括号内的文本被替换为一个长字符串,其中替换了参数。TeX 就是这样,但更复杂。

这个宏机制也解释了为什么\one\two{three}不适用于\one的结果\two{three}:宏\one采用它后面的任何单个表达式(在本例中为),\two然后扩展并替换它。

等等。所以请记住,TeX 对文本没有多次传递(标记器、语法检查器、语义检查器),而是单次传递,其中内容要么被排版,要么被解释为宏,然后被文本替换。或者更多宏。这解释了很多奇怪的情况。

答案2

if ... fi 符号相当常见(可能更常见),例如这个 shell(sh 或 bash)脚本根据参数是否为 x 来回显是或否

if [ "$1" = x ]
then

echo yes

else

echo no

fi

你认为什么是正常的,很大程度上取决于你习惯于 C 程序员的期望

(x<100)? "yes" : "no" ;

也许本质上更接近,因为它们都是类似时代的宏扩展语言,C 预处理器测试如下

#ifdef ZZZZ
#define SOMETHING
#endif

SOMETHING如果未声明宏,ZZZZ则声明宏,依此类推。

答案3

TeX 语言将要执行的对象和仅用于打印的对象混合在一起。默认情况下,当对象没有什么特殊之处时,就会打印它。这是 TeX 语言与常见过程语言之间的第一个主要区别。这种方法为您提供了非常强大的工具。这意味着使用了宏扩展语言。比较:

hello world \end      % prints hello world in TeX
print{"hello world"}  % prints hello world in procedural language

TeX 括号{}(更准确地说是带有 catcode 1 和 2 的字符)在语言中有四种不同的含义。有时这可能会导致一些小问题,但也能带来惊人的效果。含义是:(1)它们必须始终保持平衡(这由 TeX 内部算法检查)。(2)它们会影响参数读取,当它们位于参数文本的外层时,TeX 内部算法会丢弃它们。(3)它们界定框或数学子列表的组和边框(它们也界定组)。这些设置在此类组中是本地的。(4)它们界定宏的文本(之后\def或伴随的)。

因此,为括号赋予第五种含义:用于限定条件,并不是一个好主意。这就是为什么用不同的方式解决条件的原因。但宏程序员可以为用户准备面向括号的条件,但他/她从不使用这种类型的归约。

例如,过程语言程序员会说:

if (a%2 == 0) {
  x = 1;
} else {
  x = -1;
}

但是 TeX 宏程序员有更多方法可以处理条件的扩展级别:

\valX = \ifodd\valA -\fi 1 
% or:
\ifodd\valA \valX = -1 \else \valX = 1 \fi

我的意思是,TeX 是一种非常强大的工具,但只有少数人能够理解并有效利用它。不幸的是。

答案4

啊,这是一个七年前的问题,有很多完全可以接受的答案。

从“为什么”的角度,我注意到 Barbara Beeton 的评论:

当 Knuth 创建 tex 时,他打算供自己和他的秘书使用,并且他设计了他认为最适合其预期用途的语言——排版。他没有预见到它会被如此多的用户采用

和 Victor Eijkhout 的回答

TeX 不是常规的编程语言:它是一种“宏扩展语言”。

尽最大努力抓住问题的核心。

大部分原始语法都是围绕着让键盘操作尽可能符合 DEK 的使用情况¹ 而展开的,自 TeX82 发布以来的近 40 年里,宏开发中发生的许多事情都是围绕着让事情变得更加规则(在“私有@”命令名中随机放置就是一个例子)。坏的不规则性)。我认为 Frank Mittelbach 的日耳曼气质在很大程度上促成了这种事情²,他使用了 expl3 和团队提供的各种 LaTeX 扩展。但当然,LaTeX 在过去 37 年里一直杂乱无章地发展,存在很多不一致之处,包括多个键值实现和条件语法(例如,正如 Steven Segletes 所举的例子,有些宏的通用格式为⁴

\somename{CONDITION}{TRUE ACTION}{FALSE ACTION}

xparse(除其他外)提供了其条件命令的多种变体,例如,

\IfBooleanTF{ARG}{TRUE ACTION}{FALSE ACTION}
\IfBooleanT{ARG}{TRUE ACTION}
\IfBooleanF{ARG}{FALSE ACTION}

这也出现在 expl 3 语法中,例如:

\bool_if:nT {CONDITION} {TRUE ACTION}
\bool_if:nF {CONDITION} {FALSE ACTION}
\bool_if:nTF {CONDITION} {TRUE ACTION}

(总的来说,expl3 试图将 TeX 的宏语言转变为更接近于熟悉的编程语言,尽管偶尔会出现一些奇怪的情况,比如使用术语map来表示真正的foreach)。


  1. 毫无疑问,有人可以更容易地挖掘出他的评论,了解他为什么更喜欢{1\over 2}等等\frac{1}{2}
  2. 我对德国个人和机构倾向于系统地安排事物感到既敬畏又困惑³
  3. 是的,我的意思是感到困惑而不是感到有趣。
  4. 请注意,TeX 的处理器可能会对以 ... 开头的宏名称感到困惑,\if因此这种命名通常是不受欢迎的,除非它是使用原语创建的条件\newif

相关内容