我知道分号表示像Java这样的语言的结尾,但为什么呢?
我被其他人问了很多,我真的想不出一个好方法来解释它如何比仅仅使用换行符或空格更好。
它们没有发出线路终点信号,它们表示声明结束。
有些语言不需要它们,但是这些语言不允许单行或单个语句上的多个语句跨越多条线(没有像VB的_信号那样的其他信号)。
为什么有些语言允许多行语句?理念是空白是无关紧要的(行尾字符是空格)。这样可以灵活地设置代码的格式,因为格式化不是语义的一部分。
首先,分号是语句分隔符,而不是行分隔符。有些语言使用新行字符作为语句分隔符,但忽略所有空格的语言倾向于使用分号。
语言忽略空格以允许程序员根据自己的喜好格式化源代码。例如,在Java中没有区别
if (welcome)
System.out.println("hello world");
和
if (welcome) System.out.println("hello world");
这不是因为在语言的语法中每个都有一个单独的案例,而是因为空格被简单地忽略了。
这是问题的核心。要理解它,让我们考虑一个没有任何语句分隔符的小语言。它包含以下语句类型:
var x = foo()
y[0, 1] = x
bar()
在这里,y
是一个二维数组,x
被写入y
的一个条目。
现在让我们看一下这些语句,就像编译器会看到它们一样:
var x = foo() y[0, 1] = x bar()
因为没有语句分隔符,所以编译器必须自己识别每个语句的结尾,以理解输入。编译器能够这样做吗?我想在上面的例子中编译器可以做到。
现在,让我们为语言添加另一种语句:
[x, y] = ["hello", "world"]
多重赋值允许程序员一次分配多个值。在此行之后,变量x
将包含值"hello"
,而变量y
包含"world"
。这可能非常方便允许函数的多个返回值。现在,它如何与剩余的语句类型一起工作?
请考虑以下语句序列:
foo()
[x, y] = [1, 2]
首先,我们称之为foo
方法。之后,我们将1
分配给x
,将2
分配给y
。至少这是我们打算做的。这是编译器看到的内容:
foo() [x, y] = [1, 2]
编译器能够识别每个语句吗?不,至少有两种可能的解释。第一个是我们想要的。这是第二个:
foo()[x, y] = [1, 2]
这是什么意思?首先,我们称之为foo
方法。该方法应该返回一个二维数组。现在,我们在返回的数组中的[1, 2]
位置编写数组[x, y]
。
编译器无法识别语句,因为给定输入至少有两种有效解释。当然,这绝不应该在真正的编程语言中发生。在给定的示例中,它可能很容易解决,但重点是,如果没有语句分隔符,则很难设计编程语言。这很难,因为语言设计者必须考虑语句类型的所有可能的排列,以确保语言不含糊。
因此,语句分隔符有助于语言设计者最初设计语言,但更重要的是,它允许语言设计者在将来轻松扩展语言,例如通过添加新的语句类型。这是一件大事,因为一旦用您的语言编写代码,您就不能简单地更改现有语句类型的语法,因为这将导致所有现有代码不再编译。
总而言之,分号是在空格忽略语言时作为语句分隔符引入的,因为设计和扩展具有语句分隔符的语言更容易。
许多语言允许您根据需要放置多少间距。这使您可以控制代码的外观。
考虑:
String result = "asdfsasdfs"
+ "asdfs"
+ "asdfsdf";
因为您可以插入额外的换行符,所以您可以将该行分成几行而不会出现问题。语言仍然需要知道行已完成,这就是你需要分号的原因。
语言是这样做的,因为它表示statement
的结束,而不是line
的结尾,这意味着您可以压缩代码,使其更小并占用更少的空间。
拿C ++代码(#include <iostream>
):
for(int i = 0; i < 5; ++i){
std::cout << "did you know?" << std::endl;
std::cout << "; signifies **end of statement**" << std::endl;
std::cout << "**not the end of the line**" << std::endl;
}
它也可以写
for(int i = 0; i < 5; ++i){std::cout << "did you know?" << std::endl; std::cout << "; signifies **end of statement**" << std::endl; std::cout << "**not the end of the line**" << std::endl;}
一些编程语言使用它来表示语句的结束,从而使语言从语句的角度看不出白色空间。中间要做的一件事是,如果在编译时你要检查一个新行或一个分号然后你必须评估几个不同的“情况”,编译器可能会得到你想做的错误,并且需要一个查找这些情况的时间要长一些,而不是简单地在语句结尾处查找分号。一些更高级别的语言尝试减少分号使用或完全删除它以节省一些击键,这种语言更倾向于程序员的舒适度,并且通常带有各种语法糖;有人可能会争辩说,不使用分号是一种语法糖。在语言中使用或不使用分号应该根据语言试图完成的内容,C和C ++等语言主要是关于性能,Java和C#在抽象意义上比C和C ++高一点然后我们有像Scala,Python和Ruby这样的东西,它们主要是为了让编程更加舒适而牺牲性能,(Ruby公开承认这一点,而且在Python上非常明显)。那么为什么有些语言“需要”分号?
最后一件事是Javascript实际上在编译期间或IIRC之前添加了分号,因此它实际上不是分号。
简短回答:
因为其他人都这样做。
从理论上讲,语言的语句是语言设计者在解析文件时能够语法解释的语句。因此,如果语言设计者不想使用分号,则可以使用句点,短划线,空格,换行符或其他任何来表示语句的分离。
语言设计者经常使语法易于理解,以便它变得流行。
Wikipedia: Semicolon Usage in Computer Languages
因此,如果某个语言设计者创建了一种使用':-)'来表示语句结束的语言,那么1)难以阅读; 2)不习惯已经习惯使用';'的人。
回声“保重”:-)
简短回答:
因为其他人都这样做。
不,也不是每个人。此外,许多流行语言(如Python,Ruby或Visual Basic)不使用分号作为语句结尾但使用换行符。许多人,而不是“每个人”,仍然使用分号,因为历史原因,而不是理性的论证:分号在第一个计算时代取代穿孔卡格式有重要作用,但今天它可以完全丢弃。
实际上,有两种流行的方式来指定语句结束:
\
)来说明语句还没有完成。为了使代码更具可读性,使用特殊字符指定语句结尾应该是一个例外,而不是规则。