这是一个演示我的问题的人造玩具示例:
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
?
我知道上面的玩具示例很容易被重构以完全摆脱无限循环,但我真的希望在我的实际代码中拥有无限循环。相信我;)
答案 0 :(得分:6)
始终返回Int
:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}
答案 1 :(得分:4)
你也可以这样做:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
这将是类型检查,因为throw
的类型是Nothing
,这是Int
的子类型。
答案 2 :(得分:2)
见question。 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)
}
答案 3 :(得分:2)
根据SLS,while
循环的执行方式类似于:
def whileLoop(cond: => Boolean)(body: => Unit): Unit =
if (cond) { body ; whileLoop(cond)(body) } else {}
即,它返回Unit
。因此,编译器将while
视为sscce()
中的最后一个语句,因此假设您尝试返回Unit
。我认为,return count
总是会Int
返回count
。
简单的解决方案是遵循@Brian或@IonutGStan的建议,强制它返回{{1}},无论它是否真的需要它。
答案 4 :(得分:2)
从代码质量的角度来看,放弃while(true)
循环并将其替换为更具可读性的东西将是一件好事。作为一个很好的副作用,它也解决了你的问题:
def sscce(): Int = {
val rand = new Random()
var count = 1
while (rand.nextInt() != 42) {
count += 1
}
count
}