无限循环似乎混淆了 Scala 的类型系统
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
}
}
我怎样才能帮助编译器理解这个方法总是 return 一个 Int
?
我知道上面的玩具示例可以很容易地重构以完全摆脱无限循环,但我真的想要在我的实际代码中使用无限循环。相信我 ;)
总是 return 一个 Int
:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}
看到这个 question。 While 循环不 return 一个值。即它们 return Unit
这是您函数中的最后一条语句。所以,定义说它 returns 一个 Int
但实际上它 returns Unit
因此类型错误。 @ionut 的回答通过 returning 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 {}
即 returns Unit
。因此编译器将 while
视为 sscce()
中的最后一条语句,因此假定您正在尝试 return Unit
。我认为意识到 return count
将 最终 总是 return 和 Int
.
是不够聪明的
简单的解决办法就是按照@Brian 或@IonutGStan 的建议,强制设置为return count
,不管是否真的需要。
从代码质量的角度来看,放弃 while(true)
循环并用更具可读性的内容替换它会很好。作为一个很好的副作用,它也解决了你的问题:
def sscce(): Int = {
val rand = new Random()
var count = 1
while (rand.nextInt() != 42) {
count += 1
}
count
}
您还可以这样做:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
这将进行类型检查,因为 throw
的类型是 Nothing
,它是 Int
.
的子类型
这是一个演示我的问题的人造玩具示例:
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
}
}
我怎样才能帮助编译器理解这个方法总是 return 一个 Int
?
我知道上面的玩具示例可以很容易地重构以完全摆脱无限循环,但我真的想要在我的实际代码中使用无限循环。相信我 ;)
总是 return 一个 Int
:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}
看到这个 question。 While 循环不 return 一个值。即它们 return Unit
这是您函数中的最后一条语句。所以,定义说它 returns 一个 Int
但实际上它 returns Unit
因此类型错误。 @ionut 的回答通过 returning 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 {}
即 returns Unit
。因此编译器将 while
视为 sscce()
中的最后一条语句,因此假定您正在尝试 return Unit
。我认为意识到 return count
将 最终 总是 return 和 Int
.
简单的解决办法就是按照@Brian 或@IonutGStan 的建议,强制设置为return count
,不管是否真的需要。
从代码质量的角度来看,放弃 while(true)
循环并用更具可读性的内容替换它会很好。作为一个很好的副作用,它也解决了你的问题:
def sscce(): Int = {
val rand = new Random()
var count = 1
while (rand.nextInt() != 42) {
count += 1
}
count
}
您还可以这样做:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
这将进行类型检查,因为 throw
的类型是 Nothing
,它是 Int
.