[英]Infinite loop seems to confuse Scala's type system
这是一个人工玩具示例,演示了我的问题:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) { // type mismatch; found: Unit, required: Int
count += 1
if (rand.nextInt() == 42) return count
}
}
我怎样才能帮助编译器理解这个方法总会返回一个Int
?
我知道上面的玩具示例很容易被重构以完全摆脱无限循环,但我真的希望在我的实际代码中有无限循环。 相信我;)
总是返回Int
:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}
你也可以这样做:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
这将是类型检查,因为throw
的类型是Nothing
,这是Int
的子类型。
看到这个问题 。 while循环不返回值。 即它们返回Unit
,它是函数中的最后一个语句。 所以,定义说它返回一个Int
但它实际上返回Unit
因此返回了类型错误。 @ ionut的答案通过将count
作为最后一个语句返回来修复类型错误,或者这是一个递归方法。
def sscce(): Int = {
val rand = new Random()
def ssccer(count: Int): Int = {
if(rand.nextInt == 42) return count
else ssccer(count + 1)
}
ssccer(0)
}
根据SLS , while
循环的执行方式与:
def whileLoop(cond: => Boolean)(body: => Unit): Unit =
if (cond) { body ; whileLoop(cond)(body) } else {}
即,它返回Unit
。 因此编译器将while
视为sscce()
的最后一个语句,因此假设您正在尝试返回Unit
。 我不认为它很聪明地意识到return count
最终将总是返回Int
。
简单的解决方案是遵循@Brian或@IonutGStan的建议,并强制它返回count
,无论它是否真正需要它。
从代码质量的角度来看,放弃while(true)
循环并将其替换为更具可读性的东西将是一件好事。 作为一个很好的副作用,它也解决了你的问题:
def sscce(): Int = {
val rand = new Random()
var count = 1
while (rand.nextInt() != 42) {
count += 1
}
count
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.