为什么许多编程语言中的语句都以分号结尾?


130

是否有理由选择分号作为行终止符而不是其他符号?

我想知道此决定的历史,并希望答案能带来可能影响未来决定的见识。


6
Erlang和Prolog使用句号。
戴夫·克拉克2012年

13
我想知道您知道多少种编程语言。有许多不使用分号的语言。
knivil

50
我敢打赌,答案将变成类似“分号的ASCII值在用作80个字符的打孔卡上的最后一个字符时特别耐用”。
瑞安·汤普森

22
您的问题还远远不够。真正的问题是,“为什么根本没有任何符号?”
Konrad Rudolph 2012年

5
因为它在qwerty键盘的主行上?
2012年

Answers:


132

用英语将分号用于分隔语句列表中的项目,例如

她看到了三个男人:来自新西兰的杰米(Jamie);送牛奶者的儿子约翰;还有一个,弱的乔治。

进行编程时,您将分隔多个语句,并且使用句号可能会很容易混淆小数点。使用分号提供了一种易于解析的方法,可以在保持接近正常英语标点的同时分离各个程序语句。

编辑以添加
在内存昂贵,处理缓慢以及最初的编程语言正在被设计的早期,有必要将程序拆分为单独的语句进行处理。某些语言要求将每个语句放在一行上,以便回车可以用作语句定界符。其他语言允许文本布局使用更自由的格式,因此需要特定的分隔符。选择该字符作为分号,很可能是因为它与英语中使用的相似(这必须是一个假设;我当时不在那儿),因为它与其他标点符号没有冲突数学或其他语法目的所需的标记和符号。

再次编辑
某些终止符的需求可以追溯到解析语言文本的要求。早期的编译器是用汇编语言编写的,或者在某些情况下是直接用手工制作的二进制机器指令编写的。具有特殊的字符可以标识语句的末尾并分隔正在处理的文本块,这使处理变得容易得多。正如我上面所说的,其他语言也使用回车符或括号。Algol,Pascal,Ada,BCPL,B,C,PL / M和其他语言族碰巧使用分号。至于哪个人是第一个使用这个特殊角色的人,我在历史上回想起来还不够。它的选择和采用非常合理,因为

  • 它的用法反映了普通英语标点符号的用法。
  • 其他字符(例如句号)可能已经引起了混淆,因为它们已经很常用了(句号也用作小数点)。
  • 可见的标点符号允许自由格式的代码布局。
  • 在派生或更高版本的语言中使用类似的定界符可建立在所有使用较早语言的程序员所熟悉的基础上。

最后,我想在设计这些答案和评论所用的第一种语言时,花在确定答案上的时间要比决定使用分号结束语句所花费的时间更多。


19
并不完全正确。分号将句子分成多个块:每个块应该是一个工作句子,但是我们使用分号表示两个句子之间有很强的联系。它位于逗号和句号之间的中间位置,因此确实是一个停止点,但它将一个句子链接到下一个句子。上面的句子是:“她看见了三个人;杰米:来自新西兰的约翰;牛夫的儿子;乔治:一个弱的人。” 您对分号的使用可以用逗号代替。话题不大,但要旨基本上是相同的;它破坏了语句。
alex.p 2012年

40
@ alex.p实际上会以分号代替逗号,否则会导致句子混乱,这是正确的。
Ryathal 2012年

13
有关分号的重要信息:theoatmeal.com/comics/semicolon
Ed James,

7
@ alex.p:您似乎在说Ian的用法是错误的,但您可能只是在说他对我们如何使用分号的解释是不完整的。如果您说他错了,那您就错了。他对分号的使用完全是常规的,我想比您所举的例子要普遍得多。如果您只是说他没有给出详尽的解释,那么我不确定为什么甚至值得一提。
iconoclast 2012年

17
@Ian“这必须是一个假设,当时我当时不在那儿”您错过了一个绝佳的机会(正确)在那儿使用分号:)
特拉维斯·克里斯蒂安

70

许多语言都使用模仿C的语法(模仿模仿B的语法-感谢@Crollster)。从评论中可以看出,这类语言有很长的篇幅……B受到PL / I的启发,ALGOL则在前面使用了A ;作为分隔符。

由于在C中语句终止符为;,因此这些语言也照搬。

至于为什么选择它作为C中的语句终止符-可能是因为其在英语中使用“表示相互依赖的语句”

在字符集可用的存储空间有限的时候,PDP-11上也发明了C语言,因此语言的发明者必须在这些限制内工作。


8
C只是遵循了其前身“ B”使用分号的惯例
Crollster 2012年

8
B只是遵循其前身'PL / I'使用分号的惯例:)
Skomski 2012年

15
@Skomski-接下来是什么?我正在等待最后一只海龟进来;)
奥德

26
-1; 伙计们,我们都忘记了极具影响力的ALGOL吗?在您提到的所有其他内容之前,它都有分号作为语句分隔符。(不过,我不知道它是否从其他地方获得了
灵感

13
@Oded-我想您会发现它一直都是海龟。* 8')
Mark Booth 2012年

54

FORTRAN用回车符来描述语句。COBOL使用期限。LISP不使用任何内容,而是使用括号来表示所有内容。ALGOL是第一种使用分号分隔语句的语言。PASCAL遵循ALGOL的领导,使用分号分隔语句。

PL / I使用分号终止语句。有一个区别,在PASCAL中很容易看到。Ada在这一项目上遵循PL / I的领导,而不是ALGOL的领导。

以分号作为语句分隔符或终止符已被计算机科学社区迅速接受为一种有用的表示法,据我所知,随后的每种块结构语言都遵循ALGOL的领导,并使用分号来分隔或终止语句。

多年以前,我曾被告知BCPL使用分号回车符作为语句分隔符/终止符,但我本人从未使用过该语言,因此无法验证这一点。在某些时候,从BCPL后代中删除了使用回车来分隔或终止语句。BCPL产生B,B产生C,C产生C ++,Java,D以及比PASCAL和Ada少得多的思想。


2
应当指出,分号或换行符的使用最近又出现了。如果Javascript,Lua,Go和Haskell在语法上有效,则它们在换行符处都具有隐式分号。当然还有一些保留换行符作为分隔符的语言。在这里想到了Shell和Python。
Jan Hudec 2012年

2
+1代表“ 比PASCAL和Ada 少得多的深思熟虑”
Aditya 2012年

2
Algol 58(Algol 60的前身)使用分号。请注意,当时,语言的发布形式和实际输入形式之间经常会有所区别,因为输入设备非常有限:仅大写,等等。这种二分法在FORTRAN中并不真正适用,而在FORTRAN中却适用。其他语言数量。
丹·哈尔伯特

5
@kevincline:您会认为波音777是常用的吗?飞行该飞机的航空电子软件的每一行都是用Ada编写的。
John R. Strohm 2012年

2
@kevincline Skype:用Delphi(帕斯卡)编写。Microsoft尝试在更改它后对其进行了更改,但是由于无法成功移植,因此现在购买了Delphi许可证。在美国看过电视吗?该站可能运行在用Delphi编写的WideOrbit软件上。他们在市场上遥遥领先。曾经去过主题公园吗?票务系统很有可能是用Delphi编写的。帕斯卡遍布各地。只是它提供了如此强大的竞争优势,以至于许多人试图对此保持沉默,以免竞争对手发现。
梅森·惠勒

14

为什么没有其他符号?

几种语言使用了其他符号-例如,旧版BASIC使用冒号代替。

但是,我忽略了少数例外,主要有两个原因。首先,您只是在寻找明确的内容。在典型的解析器中,如果遇到足够严重的错误以致无法继续解析当前语句,则通常尝试通过直接跳到语句终止符并从重新启动解析器来使解析器恢复同步。下一条语句的开始。为此,您希望某些东西通常不会在代码中的其他任何地方出现,而分号恰好是一个没有附加其他含义的符号,因此很容易将其专用于此目的。

第二个原因有些相似,但更多地针对人们阅读/使用代码。同样,它又回到了一个事实,即您使用的实际符号无关紧要。在可能的情况下,使用读者习惯于特定目的的符号来获得可读性上的实质性优势。这并不意味着C是一种完美的语法,其他所有事物都应该严格遵循它,但这确实意味着有足够的人熟悉这种语法风格,而模糊的相似语言通过遵循它会收获很多(而损失很少)尽可能使用大致相同的语法。

我会注意到,这就像设计几乎任何其他程序一样。如果我编写的程序使用某种形式的Windows,我将尝试仅使用目标平台的本机功能。体现的许多决定在很大程度上都是武断的,并且可以以不同的方式执行而不会造成功能上的重大损失-但是同样地,在不大幅增加功能的情况下更改它们只会使用户感到困惑,而无法完成任何有用的工作。相同的基本原则适用于“应该用什么终止(或分开)某种语言的语句?” 如“滚动条的外观如何”或“树控件应如何工作?” 在所有这些情况下,决策基本上都是任意的,并且统一性本身就提供了很大的好处。

我要补充说,在许多种语言中都发生了同样的事情,只是在编程之前,我们大多数人已经习惯了这种方式,很少有人考虑它。为什么每个人都用“ +”表示加法,或用“-”表示减法?因为符号的形状无关紧要,但是每个人都同意对每个符号应用相同的含义非常重要。


很好(+1分),尽管我不太同意“大部分是任意的”部分。我认为肯定有一些事情更直观,而另一些则不那么直观。在Windows使用X关闭窗口的过程中,使用了一些(也许只是模糊地连接)预先存在的符号。在OS X对颜色的使用中,肯定会带有强烈的象征意义。(我暂时忽略M $ Windows可能从X Windows窃取了X,因为我不记得使用了什么。)
iconoclast 2012年

3
@Brandon:我当然不打算说GUI设计的所有部分都是任意的-也许我应该说“一些”而不是“大多数”。不是为“关闭窗口”图标定义任何特定形状的X而是由单个窗口管理器决定的。
杰里·科芬

据我所知,原始的Dartmouth BASIC仅使用回车符来终止语句(即,每行一个语句)。我认为一行中的多个语句(以冒号分隔)是Microsoft的扩展。
约翰·斯特罗姆

7

分号最初是在Algol 60中提出的,用作语句分隔符,而不是终止符。

在Algol 60之前,Fortran是唯一存在的高级编程语言,它要求每个语句都在单独的行上。像do循环一样,跨越多行的语句被认为是奇怪的,它们被视为“语句块”。

Algol 60的设计人员意识到,语句需要分层结构(if-then-else,do-loop,case语句等),并且它们可以嵌套在彼此内部。因此,将每个语句放在单独的行上的想法不再有意义。S1形式的语句的顺序组成;S2; ...; Sn可选地包含在开始 - 结束括号中,被称为复合语句,并且适合Algol 60所设想的语句的层次结构。因此,在这里,分号显然是语句分隔符,而不是终止符。

这在实践中引起了问题。Algol 60也有一个“空语句”,它没有写任何内容。因此,可以写出“ 开始 S1;结束 ”,分号看起来好像在终止S1。但是Algol 60编译器确实将其视为S1和其后的不可见空语句之间的分隔符。这些微妙之处对于实际的程序员来说有点多。他们已经习惯了诸如汇编语言和Fortran之类的面向行的语言,他们确实认为分号是语句的终止符。编写程序时,通常将分号放在语句的末尾,如下所示:

    a [i]:= 0;
    我:=我+1

分号确实看起来像第一个语句的终止符。如果程序员将分号视为终止符,则这样的语句将产生语法错误:

    如果我> 0,那么
      a [i]:= 0;
    其他
      a [i]:= 1;

因为分号终止了“ if”,所以“ else”变得悬空了。程序员们被彻底弄糊涂了。

因此,PL / I,即IBM面向行的Fortran的继承者,决定将分号作为语句终止符而不是分隔符。程序员对此选择感到满意。大多数编程语言都紧随其后。(Pascal拒绝了这种趋势,但其继任者Ada放弃了这一趋势。)

[注:维基百科上有关编程语言比较的文章有一个很好的表格,总结了如何在各种编程语言中处理分号。]


6

这几乎是纯粹的猜测工作,但是查看受限于ASCII值的标准QWERTY键盘,终止/分隔的自然字符将是。!?::;。和回车。!!中的一个:应立即取消获得多个密钥的资格,并且语句终止将是很常见的事情。句号将被取消资格,因为它们很容易与小数点混淆,由于初始计算机的空间有限,这会使它们不必要地复杂化为终止符。如果代码行的长度可能大于屏幕上一行上显示的行数,那么回车符将被取消资格,因此,当必须水平滚动行时,阅读程序会更加困难,或要求其他字符在下一行上创建延续,这又增加了复杂性。离开了; 作为选择中的一种,相比于;之所以选择分号,是因为它更易于键入,不会造成混淆,因为它为有限意义的字符增加了含义,并且也因为复杂的使用情况而真正没有特殊情况,因此使之不太复杂。

选择分号是因为它是基于懒惰和简单性的最佳字符。


你在这里有一个好点;我只会将“选择”(很难证明)改写为“ ...分号之所以获胜,是因为它是基于懒惰和简单性的最佳角色”
gnat

2
几乎不。以分号作为语句终止符/分隔符的方法始于ALGOL(1958),该方法早于ASCII(工作开始于1960年,1963年首次发行,1967年主要发行,1986年最后更新)。
约翰·斯特罗姆

@ JohnR.Strohm对我来说真是个新闻,但是对我而言,所有这些都是非常古老的历史
Ryathal 2012年

6
这是一个很好的理论,但是现实是,无论如何击键都需要使用Shift键才能到达分号,直到现代键盘输入出现在70年代为止。(在Wiki文章的底部附近有几张漂亮的照片:en.wikipedia.org/wiki/Keypunch)最有可能只是基于自然的英语规则,这种流行同时流行。(我将包括50年代后期的所有语言:ALGOL,FORTRAN,COBOL和SQL,不包括LISP。)ALGOL的分号只是使用的许多英语约定中的一种,后来BASIC对其进行了进一步扩展。
SilverbackNet 2012年

@SilverbackNet,这就是为什么“纯猜测工作”可能不应该成为此处答案的基础。
user1717828

6

这很大程度上是一个任意选择。一些语言做出了其他选择。COBOL以该.字符终止语句。FORTRAN,BASIC和Python通常以换行符终止语句(对于多行语句使用特殊语法)。Lisp用括号将其声明括在括号中。

;语句分隔符/终止符之所以如此流行,主要原因是当今大多数流行语言都基于使用该约定的ALGOL

而不是其他符号?

您还能选择什么其他符号?

ASCII字符#$ @ [] ^ _`{|}〜并不总是出现在ISO 646之类的早期字符编码中。

这些字符()*+-/<=>通常用作数学运算符,如果用作语句终止符,则会产生歧义。

product = a * b *  // If '*' were a statement terminator,
c * d *            // Are there two factors, or four?

类似的问题将适用于'",通常用作字符串定界符。,,通常用于分隔函数参数,而.,通常用作小数点(或在类似的结构中用作分隔符some_struct.some_field)。

离开!%&:;?

选择!?可能不会造成技术上的困难,但是它们的英语含义会使程序产生错误的心情。

print(x)?  # Yes, you should.
           # It's an IMPERATIVE language; stop questioning my commands.
print(x)!  # OK!  You don't have to shout!

&作为语句分隔符(而不是终止符),这将是更明智的选择,因为

do_thing_a() &
do_thing_b()

可以理解为一个命令做事情,并随后做的事情B.但是,大多数语言与&运营商使用它作为一个逻辑或按位AND来代替。

%符号可能会导致类似这样的语句混乱interest_rate = 2.99%(它将变量设置为2.99而不是预期的0.0299)。当然,众所周知的数学意义%并没有阻止C将其用作余数运算符。

使叶片:;

: 是一个明智的选择,并且确实在大多数BASIC方言中用作行内语句分隔符。

但是;有英语语法。它可用于分隔句子中的从句。


3

与其尝试回答您的标题问题,不如将重点放在您的隐式问题上:

我想知道此决策的历史,并希望答案能带来见解,从而可能影响编程语言的设计和实现中的未来决策。

如果您想了解编程语言的设计和实现历史,并且对过程有更多的了解,那么“ 编程语言历史会议”的会议记录将是一个很好的起点。(我认为您将需要ACM成员身份才能访问该程序。)

为什么许多编程语言中的语句都以分号结尾?是否有理由选择分号作为行终止符而不是其他符号?

以您的标题问题为例,您可能希望通过阅读HOPL程序来尝试回答该问题,我想提供以下几点:设计新编程语言的人们之所以这样做,是因为他们认为自己知道的是损坏/不足。一方面,他们的新语言旨在解决这一缺陷。另一方面,语言设计师还将从他们认为不错的其他语言中复制设计元素,或者他们只是不更改自己不会遇到问题的那些元素。

特别是最后一部分很重要:与其试图找出哪一种编程语言是第一个使用分号作为终止符的编程语言,以及为什么很多其他编程语言都复制了这种语言,不如通过查找复制的语言来学习更多它。例如,虽然Smalltalk从Simula那里获得了很多启发,但它并没有复制其语法,尤其是使用分号作为语句终止符。它将终止符(实际上是分隔符)更改为句号,并将分号用于其他内容。相反,曾经使用分号作为语句终止符的第一种语言可能有理由将其从之前的语言中更改。也有可能是第一种语言引入了语句终止符的整个概念(或独立于其他语言而引入),并且分号由于某种原因而被使用,但现在已经不及时了。(我怀疑后者就是这种情况,因为没有其他答复者能够从介绍分号的人那里找到报价,而不是对为什么分号是个好选择提供了新的假设。)但是,重申一下我的观点。点,我认为您将通过了解语言设计师为何更改事物而不是为什么他们复制/保留它们来学到更多。当人们更改事物时,他们通常希望或不得不解释更改,而当人们复制或保持不变时却不这样做,因为“我们为什么要更改它?这就是完成的方式!”


2

它的可见性。

早期的语句分隔符为“。”。就像在COBOL和换行符中一样,在FORTRAN中回车。

CR被证明是有局限性的,因为它使得难以在多行上传递语句。

句号停止引起了一个更有趣的问题。当您阅读英文文本时,您的大脑会在下意识的水平上处理句号,您会意识到句子已经结束,可以喘口气,但是您并没有真正注意到。这表明了这一点。同样在许多字体中,“。” 是有时显示为单个像素的最小可能字符。丢失或多余的时间已成为COBOL程序错误的最常见原因。

因此,从早期错误中吸取教训,ALGOL选择了一个特定的终止符,该终止符将使一条语句流经多行,并选择了一个易于阅读且易于阅读的语句。分号既大又普通,足以使普通英语无法下意识地处理。


1

据我了解,之所以选择它,是因为除了回车/换行之外,还需要一个明确的语句终止符。早在80列的屏幕时代,实际上只有一行代码跨越多行换行很常见,以至于将\ r或\ n用作语句终止符是行不通的。

分号之所以方便,是因为它们不用于逻辑/数学语句中。因此,它们在很大程度上不会与语句的实际内容冲突。


我个人认为,继续使用分号以及将行数保持在80个字符以下的样式要求是坦率的愚蠢和过时的做法。诸如python之类的语言已广泛证明,没有它们,您可以编写易于理解,简洁的代码。另外,如果您遇到的行数超过80个字符的问题,则需要更大的监视器。


3
早在黑暗时代,就没有“ 80列屏幕”。有80列打孔卡,并且打印机的列数不同。(大约130左右很普遍。)FORTRAN在卡的末尾终止了语句,但允许延续卡继续该语句。延期卡的标记是在卡的第6栏中打出一个字符。(任何字符都可以使用。根据当地惯例,通常会看到一个+号或一个数字,多个连续卡的数字向上计数。)
John R. Strohm 2012年

1
像Python这样的语言对于C早期存在的计算机来说是行不通的。使用语句终止符使解析变得更简单,并且减少几十年前编译器的内存和CPU负载非常重要。尤其是在您花了第二秒花费CPU时间的那些计算机上。
Gigatron 2012年

@Gigatron -我是指对使用马车返回到结束的声明,而不是任何的蟒蛇的更高级别的方面。
假名称

1
@Gigatron,您可能想了解一下LISP,尤其是IBM 704上的LISP的早期历史。您可能会惊讶于Ancients可以做什么,甚至可以使用石刀和熊皮。
约翰·斯特罗姆

1
@Gigatron:FORTRAN在同一台计算机上运行,​​并且使用换行符分隔语句(对多行语句使用特殊语法)。
dan04 '14

0

这里有两个问题:为什么ALGOL使用分号,以及为什么其他语言采用了分号。

第一个问题已经在这里以多种方式回答。

作为第二篇,ALGOL被广泛用作算法编写的伪代码语言。因此,分号很快就成为不同语言用户的常识。很自然地,他们被选为年轻的语言。


0

我可能是错的,但是我认为这与以下事实有关:在许多汇编器中,分号通常用于在指令后添加注释。后面的所有内容;均为注释,不再是说明本身的一部分。

然后,当您在解释器中键入指令时,需要终止它们。短指令(例如数学表达式)可以通过简单地按Enter键来终止,告诉解释器表达式已准备好进行计算并产生结果。但是有时人们想要为指令输入多行代码,因此一种实现方法是使用某些特殊字符作为指令的终止符,而不是仅依赖Enter键。这样,用户可以一次输入更多行代码,因为Enter尚未将其发送给解释器。只有当解释器在用Enter输入的行中找到终止字符时,它才最终执行该字符并计算其结果。

现在将这两件事结合在一起,分号似乎是终止符的明显选择:它告诉指令部分在哪里结束,注释部分在哪里开始,因此当解释器在一行中遇到它时,它知道可以刷新缓冲到目前为止表达式的所有行并执行它,因为指令刚刚结束,现在我们在注释中(嗯,至少直到此行的末尾,因为下一行将在代码中开始再次进入模式,开始新的表达式/指令)。

当然,这是假定将分号重新用作指令终止符的人使用的实际上是分号。如果它是其他任何字符,我们可能最终会得到一个不同的指令终止符。

Inb4:不,这不是历史记录。我没有任何证据表明这是分号实现的实际方式。这就是我想象的可能发生的方式。


-1

大多数语言都使用分号,因为它已被广泛用于此目的,并且进行更改毫无意义。

考虑到第一种语言做出选择,您必须考虑哪些替代方法。在设计语言时,您希望所需的字符可用,并且此时的字符集被编码为6位,通常保留一些模式,通常未明确定义某些字符(有关以后的内容,请考虑一下ISO-646的变种国家-美国的变体以及知道名字的ASCII下-这重用代码为“普通”字符,例如[#或者$,看看在上下文中的效果,其中只有一半多的代码位置可用,字母和数字保留其中的一半以上)。

可能没有其他字符可以直观地用作语句分隔符(.可能已经是该条件的唯一重要竞争者),并且在解析和词汇化理论仍处于阐述阶段(.现在是现在)的情况下,没有引入词汇或解析困难。毫无疑问,因为它的实数用法)。


-1

使用分号的另一个原因是因为它是我们不需要或经常使用的字符之一。

假设我们更经常地将它用作变量名或其他名称,并且如果将分号用作关键字或运算符,则对于编译器而言这将是符号冲突,因此使用不通常在编码中使用。

我相信C风格的编程语言使其变得流行,然后新的编程语言的作者不想重新发明轮子,直到现在,他们仍在继续使用它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.