在我看来, Kotlin
中出现了一个非常奇怪的编译器错误因此,我将代码简化为最简单的形式。该代码没有意义,但是尝试了解错误的来源要容易得多。
我已将代码发布到Kotlin Playground中。因此,我不依赖计算机的任何本地配置,并且该错误可以在任何人的任何位置立即重现。
我的完整代码
data class Pilha(
var funs: ArrayList<Int>
= arrayListOf<Int>()
)
var AP: Array<Pilha> = Array<Pilha>(5) { Pilha() }
fun main() {
var ele: String=""
var cl: String = ""
when (ele) {
"soul" -> {
with(AP[0]) {
when {
(cl == "%") -> {
if (funs[0]==1) // <= error in this line
cl = "a"
}
cl == "xU" -> {
// If I comment this line, the error disappears
funs.add(2)
}
else -> { cl="b" } // else of inner when
} // when
} // with
} // "soul"
else->{ cl="c"} // else of outer when
} // when
println("ok")
} // main
错误消息
if must have both main and 'else' branches if used as an expression
此错误在此行显示
if (funs[0]==1)
如果我对此行发表评论,错误就会消失
funs.add(2)
这很麻烦,因为很明显这是有效的if
流控制语句。我没有使用if
作为表达式。
显然,在此else
上放置一个死掉的else {}
(if
)也可以解决该错误,但不作解释。
科特琳游乐场:
更新:正如Pawel向我指出的那样,这是一个类型返回冲突的问题,链接到with
语句。由于我是经典的 Pascal 程序员,因此我使用with
来了解Pascal用户是如何做到的。
为此,最好如Pawel所述,使用object.apply {}
。因此,可以像with
一样直接使用对象的属性和方法,而无需在方括号({})内插入访问点。
答案 0 :(得分:1)
您正在使用具有with(AP[0]) { ... }
的lambda签名的T.() -> R
函数。它需要lambda内部的返回值,并且其中的最后一条语句是when
块,因此它用作表达式来确定返回值。
引起错误是因为在cl == %
和funs[0]!=1
的情况下,无法确定要返回的值。
使用不需要返回值的作用域函数(例如,带有签名with
的{{1}})替换您的AP[0].apply { ... }
,以解决此问题。
编辑:为什么注释掉T.() -> Unit
“修复”错误?
这是因为该调用返回了funs.add(2)
值,该值更改了整个Boolean
块的签名:
when
现在,当您注释掉// this when block can be used as an expression because it returns value of type Any
when {
(cl == "%") -> if (funs[0]==1) cl = "a" // if true returns Unit, else undefined
cl == "xU" -> { funs.add(2) } // returns Boolean
else -> cl="b" // does not return value (Unit)
}
或将第二种情况更改为funs.add(2)
时,这会使整个{funs.add(2) ; Unit }
块的返回类型成为when
,这意味着它不再用作表达式和返回值不是必需的。
Unit