编程语言中花括号 { } 的简明历史
???? “Python猫” ,一个值得加星标的公众号
花下猫语:今天分享的文章,确切地说该称为“编程语言中花括号的起源”,主要介绍了早期编程语言中代码块定界符的演变过程。Python 是在 C 语言之后发明的,对于花括号,它采取了批判扬弃的态度。C 语言的徒子徒孙比较多,所以花括号遍地开花,不用花括号的语言反而显得特立独行了……
作者 | Michael McMillan
译者 | 弯月,责编 | 夕颜
出品 | ****(ID:****news)
众所周知的标志代码块起始和结尾的大括号是什么时候开始成为编程语言的一部分的呢?或者更重要的是,代码块何时成了编程结构的重要组成部分?
我希望通过本文回答这些问题。
无代码块的语言
熟悉C语言语法风格的程序员都对编程块很熟悉。C、C++、Java、JavaScript以及许多其他语言中,所有主要编程结构都是代码块。换句话说,这些编程结构都被放到了代码块中,而代码块的标志就是起始和结尾的大括号。
严格来说这并不完全正确,例如if语句和循环这两种结构,如果其主体部分只包含一条语句,那么可以不使用代码块。但是,在过去几年,编程风格的专家们都建议所有编程结构的主体都应该放在代码块中(参见Douglas Cockroft的《JavaScript语言精粹》一书,其中的解释更具说服力)。
但是,第一个高级编程语言并没有代码块。
我以上世纪五十年代时的FORTRAN语言为例说明。高德纳在他那篇针对早期高级语言的评论《The Early Development of Programming Languages》(该文章在他的书《Selected Papers on Computer Languages》一书中重印)中比较了几个早期编程语言的特性。他的比较方法是演示某段程序用几种语言怎样编写。这段程序实现了一个叫做TPK的算法,我们来看看用现代的JavaScript怎样编写:
你不必在意这段程序的功能。这里的重点是,这段程序展示了高德纳认为的现代编程语言中的所有重要特性。
我前面说过,高德纳使用该算法比较了几种编程语言,其中一种语言就是现在人们公认的第一个真正的高级语言。下面是高德纳编写的用Fortran语言实现的TPK算法:
我不想详细介绍Fortran的语法,但你可以很清晰地看到,该语言没有代码块。函数定义在某一行上,而不是定义成了一个块。DO循环使用行标号来控制循环。当时的高级语言还没有将组合语句分组成代码块的概念,所以这些语言依然需要依赖goto来控制程序流程。
这段代码是高德纳使用1957年的Fortran编写的。在1957~1960年之间,一种新的语言出现了,那就是ALGOL,它弥补了许多Fortran等高级语言的不足之处。
ALGOL中的代码块
ALGOL编程语言于1958年首次提出,尽管最流行的版本是Algol 60。Algol语言的特性之一就是能够将语句分组,变成组合语句,也叫代码块。每个Algol程序都可以认为是一个代码块,因为程序通常包含一条或多条语句(因此称为“组合语句”)。Algol的开发者认为,许多编程场景(如条件判断和循环)都需要将多条语句作为一个整体考虑。
Algol使用关键字begin和end表示代码块的开始和结束。代码块可以嵌套在其他代码块中,外部的代码块叫做主代码块,而内部的代码块叫做子代码块。例如,下面这段Algol程序就包含嵌套的代码块:
该程序将会按照顺序输出数字2和1。
下面是在Algol的if语句中使用代码块的例子:
下面是在Algol的for语句中使用代码块的例子:
下面来看看使用Algol语言编写的TPK程序,可以看到,与Fortran相比,代码块结构可以让程序更清晰:
可以看出,Algol的代码块结构让程序更像我们今天使用的语言。
转向BCPL
块结构语言语法的下一个改变就是Martin Richards于1967年在剑桥大学发明的BCPL语言。在1960~1967年间Algol语言开发的初始阶段,编译器开发者和系统开发者一直在寻找一种方法,使用机器语言和汇编语言之外的语言来开发系统程序(如操作系统)。之所以这里强调BCPL,是因为它发展和精炼后变成了由Ken Thompson发明的B语言,后来又发展成了C语言。
Richards开发的BCPL语言是一种系统语言,它有汇编语言同样的效率,但语法更像Algol等高级语言,所以编写程序更容易,效率也更高。这意味着Algol等高级语言的许多特性必须用一种更高效的方式包含在BCPL中。
实现这种高效的方式之一就是将代码块的标志从单词(begin和end)改成符号。对于组合语句和代码块,Richards建议使用符号$(和)$作为开始和结束标记。这些符号称为“节括号”。
在BCPL中,如果将$(和)$与if语句或循环等结构一起使用,则它们表示一个组合语句。如果$(包含一些定义,则它们表示一个代码块。
例如,下面是在BCPL中使用if语句和组合语句的例子:
下面是BCPL代码块的例子:
这里,起始记号表示代码块的开始,因为它后面紧跟着声明。
$(和$)变成了C语言中的大括号
在1968年或1969年前后,贝尔实验室的Ken Thompson和Dennis Ritchie开始使用系统编程语言开发操作系统。实际上,Thompson最初想使用Fortran,但很快就放弃了,因为他发现Fortran无法实现。因此他决定修改BCPL语言来创造一种更合适的系统语言,于是B语言诞生了。
尽管B语言更接近Thompson和Ritchie想要的系统语言,但仍然无法完全满足要求,于是Ritchie开始开发另一种语言,称为NB,意思是New B。NB并没有存活太久,最终被另一种全新的语言代替,这个全新的语言最后被称为C。如果你对C语言如何从BCPL、B和NB发函而来,我建议你阅读一下Dennis Ritchie的《History of the C Language》。
许多从B语言中继承到NB再继承到C语言中的特性,都经过了Thompson的修改,其中之一就是操作符缩写。为了将语言放入当时内存十分有限的计算机中,这些修改是必须的。例如,Thompson创造了组合赋值运算符(如+=)和自增(++)和自减(--)运算符,以便让语言更有效率。这也导致BCPL中的其他符号被简化,如$(和)$就被改成了{和}。
现状
今天的许多语言已经采用大括号作为代码块的主要标志,特别是那些接近C风格的语言,如C++、Java、C#和JavaScript。
更有意思的是,新的语言也采用了大括号,如Go和Rust。实际上,Go语言要求每个条件语句或循环结构都使用大括号,这遵循了编程专家们的建议:即使不必要,每个结构也都应该使用大括号。
原文链接:
https://medium.com/better-programming/a-brief-history-of-the-curly-brace-in-programming-5b3eacdc3f7a
优质文章,推荐阅读:
感谢创作者的好文