[英]Infinite loop seems to confuse Scala's type system
Here is an artificial toy example that demonstrates my problem: 这是一个人工玩具示例,演示了我的问题:
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
}
}
How can I help the compiler understand that this method will always return an Int
? 我怎样才能帮助编译器理解这个方法总会返回一个
Int
?
I know the above toy example could easily be refactored to get rid of the infinite loop altogether, but I really want to have the infinite loop in my actual code. 我知道上面的玩具示例很容易被重构以完全摆脱无限循环,但我真的希望在我的实际代码中有无限循环。 Trust me on this ;)
相信我;)
Always return an Int
: 总是返回
Int
:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}
You can also do: 你也可以这样做:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
this will typecheck because the type of the throw
is Nothing
, which is a subtype of Int
. 这将是类型检查,因为
throw
的类型是Nothing
,这是Int
的子类型。
See this question . 看到这个问题 。 While loops don't return a value.
while循环不返回值。 ie they return
Unit
which is the last statement in your function. 即它们返回
Unit
,它是函数中的最后一个语句。 So, the definition says it returns an Int
but it actually returns Unit
thus the type error. 所以,定义说它返回一个
Int
但它实际上返回Unit
因此返回了类型错误。 @ionut's answer fixes the type error by returning count
as the last statement or here is a recursive approach. @ 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)
}
Per the SLS , a while
loop is executed similarly to: 根据SLS ,
while
循环的执行方式与:
def whileLoop(cond: => Boolean)(body: => Unit): Unit =
if (cond) { body ; whileLoop(cond)(body) } else {}
ie., it returns Unit
. 即,它返回
Unit
。 So the compiler sees the while
as the last statement in sscce()
, and therefore assumes that you're trying to return Unit
. 因此编译器将
while
视为sscce()
的最后一个语句,因此假设您正在尝试返回Unit
。 I don't think it's smart enough to realize that return count
will eventually always return an Int
. 我不认为它很聪明地意识到
return count
最终将总是返回Int
。
The simple solution is to follow the suggestion of @Brian or @IonutGStan, and force it to return count
, whether it truly needs it or not. 简单的解决方案是遵循@Brian或@IonutGStan的建议,并强制它返回
count
,无论它是否真正需要它。
From a code quality standpoint, it would be good to ditch the while(true)
loop and replace it with something more readable. 从代码质量的角度来看,放弃
while(true)
循环并将其替换为更具可读性的东西将是一件好事。 As a nice side effect, it also solves your problem: 作为一个很好的副作用,它也解决了你的问题:
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.