Kotlin提供“分号推理”:在句法上,子句(如语句、声明等)被伪标记半分隔,后者代表“分号或换行符”。在大多数情况下,在Kotlin代码中不需要分号。
这就是语法页面的意思。这似乎意味着在某些情况下需要指定分号,但它没有指定分号,下面的语法树并不能完全说明这一点。此外,我怀疑在某些情况下,该功能可能无法正常工作并导致问题。
因此,问题是何时应该插入分号,为了避免编写错误的代码,需要注意的拐角情况是什么?
发布于 2016-09-04 16:45:09
如果分号对编译器来说不明确,那么您只需要指定分号,如果没有分号,就会导致明显的编译器错误。
的规则是:不要担心这一点,根本不使用分号(除了下面的两种情况之外)。编译器会告诉你,当你弄错了,保证。即使您意外地添加了一个额外的分号,语法高亮显示它是不必要的,并警告“冗余分号”。
两种常见的半冒号情况:
具有枚举列表以及枚举中的属性或函数的枚举类需要在枚举列表之后使用;,例如:
enum class Things {
ONE, TWO;
fun isOne(): Boolean = this == ONE
}在这种情况下,如果不能正确执行,编译器将直接告诉您:
错误:(y,x) Kotlin:期待';‘在最后一个枚举条目之后或'}’关闭枚举类主体
否则,唯一的其他常见情况是在同一行上执行两个语句时,可能是为了简洁起见:
myThingMap.forEach { val (key, value) = it; println("mapped $key to $value") } 在最后一个例子中没有分号会给你一个更神秘的错误,当它混淆了你在做什么。很难将一些代码作为分号分隔的两个语句有效,而分号被移除并成为一个分号时也是有效的。
在过去,还有其他情况,比如类的初始化块,它在Kotlin1.0之前是更“匿名”的{ ... },后来变成了init { ... },它不再需要分号,因为分号更加清晰。这些案件不再保留在语言中。
对此特性的信心:
此外,我怀疑在某些情况下,该功能可能无法正常工作并导致问题。
该特性运行良好,没有任何证据表明该特性存在问题,多年的Kotlin经验没有发现任何已知的这种特性适得其反的情况。如果缺少的;有问题,编译器将报告错误。
搜索我所有的开源Kotlin,以及我们内部相当大的Kotlin项目,我发现除了上面的案例之外,没有任何分号--而且总共很少。支持“不要在Kotlin中使用分号”的概念。
但是,您可以有意地设计这样一种情况:编译器不报告错误,因为您创建的代码是有效的,在分号和不带分号时具有不同的含义。如下所示(@Ruckus对答案的修改版本):
fun whatever(msg: String, optionalFun: ()->Unit = {}): () -> Unit = ...
val doStuff: () -> Unit = when(x) {
is String -> {
{ doStuff(x) }
}
else -> {
whatever("message") // absence or presence of semicolon changes behavior
{ doNothing() }
}
}在这种情况下,doStuff被分配给whatever("message") { doNothing() }调用的结果,它是()->Unit类型的函数;如果添加分号,它将被分配函数{ doNothing() },它也是()->Unit类型的函数。因此,代码在两方面都是有效的。,但是我还没有看到这样的事情是自然发生的,,因为一切都必须完美地排列起来。hat算子会使这种情况变得不可能,而且由于强烈反对的意见和时间限制,它被考虑了,但在1.0之前就被放弃了。
发布于 2016-09-05 07:28:18
除了Jayson的答案外,我还遇到了另一个需要分号的奇怪的边缘情况。如果您在一个不使用return语句返回函数的语句块中,则需要一个分号。例如:
val doStuff: () -> Unit = when(x) {
is String -> {
{ doStuff(x) }
}
else -> {
println("This is the alternate"); // Semicolon needed here
{ doNothing() }
}
}没有分号,Kotlin认为{ doNothing() }语句是println()的第二个参数,编译器报告一个错误。
发布于 2017-01-19 21:26:07
科特林似乎大多热切地推断分号。似乎有例外(如Jayson的枚举示例所示)。
通常,类型系统会捕获严重推断的分号,但下面是编译器失败的一些情况。
如果调用的参数位于下一行(包括括号),Kotlin将假定参数只是一个新的带括号的表达式语句:
fun returnFun() : (x: Int) -> Unit {
println("foo")
return { x -> println(x) }
}
fun main(args: Array<String>) {
println("Hello, world!")
returnFun()
(1 + 2) // The returned function is not called.
}更常见的情况可能是:在下一行中有一个带有表达式的返回。大多数情况下,类型系统会抱怨没有返回值,但是如果返回类型是Unit,那么所有的赌注都取消了:
fun voidFun() : Unit {
println("void")
}
fun foo() : Unit {
if (1 == 1) return
voidFun() // Not called.
}
fun bar() : Unit {
if (1 == 1)
return
voidFun() // Not called.
}如果bar函数不能放在一行上,那么return voidFun()函数可能会发生。也就是说,开发人员必须将函数的调用写在一个单独的行上。
https://stackoverflow.com/questions/39318457
复制相似问题