Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 分号推理的规则是什么?_Kotlin_Syntax_Grammar - Fatal编程技术网

Kotlin 分号推理的规则是什么?

Kotlin 分号推理的规则是什么?,kotlin,syntax,grammar,Kotlin,Syntax,Grammar,Kotlin提供了“分号推理”:在语法上,子内容(例如语句、声明等)由伪标记SEMI分隔,它代表“分号或换行符”。在大多数情况下,Kotlin代码中不需要分号 这是网页上说的。这似乎意味着在某些情况下需要指定分号,但它没有指定分号,下面的语法树也没有明确说明这一点。此外,我怀疑在某些情况下,此功能可能无法正常工作并导致问题 因此,问题是什么时候应该插入分号?为了避免编写错误代码,需要注意哪些特殊情况?您只需要在分号对编译器不明确的情况下指定分号,如果没有分号,则会导致明显的编译器错误 规则是:不

Kotlin提供了“分号推理”:在语法上,子内容(例如语句、声明等)由伪标记SEMI分隔,它代表“分号或换行符”。在大多数情况下,Kotlin代码中不需要分号

这是网页上说的。这似乎意味着在某些情况下需要指定分号,但它没有指定分号,下面的语法树也没有明确说明这一点。此外,我怀疑在某些情况下,此功能可能无法正常工作并导致问题


因此,问题是什么时候应该插入分号?为了避免编写错误代码,需要注意哪些特殊情况?

您只需要在分号对编译器不明确的情况下指定分号,如果没有分号,则会导致明显的编译器错误

规则是:不要担心这一点,也不要使用分号(以下两种情况除外)。编译器会在您出错时告诉您,这是肯定的。即使您不小心添加了一个额外的分号,语法突出显示也会显示“多余分号”警告,这是不必要的

分号的两种常见情况:

具有枚举列表以及枚举中的属性或函数的枚举类需要
在枚举列表之后,例如:

val doStuff: () -> Unit = when(x) {
    is String -> {
        { doStuff(x) }
    }
    else -> { 
        println("This is the alternate");  // Semicolon needed here
        { doNothing() }
    }
}
enum类事物{
一,二,;
fun isOne():Boolean=this==ONE
}
在这种情况下,如果您未能正确执行,编译器将直接告诉您:

错误:(y,x)Kotlin:应为“;”在最后一个枚举项或“}”之后关闭枚举类主体

否则,唯一的其他常见情况是在同一行上执行两条语句,可能是为了简洁起见:

myThingMap.forEach{val(key,value)=it;println(“mapped$key to$value”)}
最后一个例子中没有分号会给你一个更神秘的错误,让你搞不清楚你在做什么。当分号被删除并成为一个分号时,要使某些代码同时作为两个语句有效(用分号分隔)是非常困难的

在过去,还有其他一些情况,比如类的初始化块,在Kotlin 1.0之前更为“匿名”
{…}
,后来成为
init{…}
,不再需要分号,因为分号更清晰。这些案例不再保留在语言中

对此功能的信心:

此外,我怀疑在某些情况下,此功能可能无法正常工作并导致问题

该功能运行良好,没有任何证据表明该功能存在问题,多年的Kotlin经验也没有发现任何已知情况下该功能会适得其反。如果缺少
有问题编译器将报告错误

搜索我所有的开源Kotlin,以及我们内部相当大的Kotlin项目,除了上面的例子之外,我没有找到分号——而且总共很少。支持“不要在Kotlin中使用分号”作为规则的概念

但是,您可能会故意设计这样一种情况,即编译器不会报告错误,因为您创建的代码是有效的,并且在有分号和没有分号的情况下具有不同的含义。如下所示(由@Ruckus修改的答案):

fun whatever(msg:String,optionalFun:()->Unit={}):()->Unit=。。。
val doStuff:()->单位=时间(x){
是字符串->{
{doStuff(x)}
}
else->{
无论什么(“消息”)//分号的缺失或存在都会改变行为
{doNothing()}
}
}

在这种情况下,doStuff被分配调用
任意(“消息”){doNothing()}
的结果,这是
()->Unit
类型的函数;如果添加分号,则会为其分配函数
{doNothing()}
,该函数的类型也是
()->Unit
。因此,代码在两方面都是有效的但我没有看到这样的事情自然而然地发生,因为一切都必须完美地排列。由于强烈的反对意见和时间限制,这本书在1.0版之前就被考虑过了。

除了Jayson Minard的答案之外,我还遇到了另一个奇怪的边缘案例,需要分号。如果您所在的语句块返回函数而不使用return语句,则需要分号。例如:

val doStuff: () -> Unit = when(x) {
    is String -> {
        { doStuff(x) }
    }
    else -> { 
        println("This is the alternate");  // Semicolon needed here
        { doNothing() }
    }
}
没有分号,Kotlin认为
{doNothing()}
语句是
println()
的第二个参数,编译器报告了一个错误。

Kotlin似乎主要是急切地推断分号。似乎有例外(如Jayson Minard的枚举示例所示)

通常,类型系统将捕获错误推断的分号,但以下是编译器失败的一些情况

如果调用的参数在下一行(包括括号),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.
}

如果
return voidFun()
不能放在一行中,则可能会出现
bar
函数。也就是说,开发者只需在单独的一行中编写对函数的调用。

@JaysonMinard我不是JavaScript方面的专家,我只是知道有些语言结构看起来不错,但实际上并不正确。它们的问题是,在你发现程序中的错误之前,你不知道有问题,而错误可能会在你犯错后很快发生,也可能不会发生。我很确定JavaScript没有或几乎没有问题的表达式