繁体   English   中英

无限循环似乎混淆了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
  }
}

我怎样才能帮助编译器理解这个方法总会返回一个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)
}

根据SLSwhile循环的执行方式与:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM