Scala while循环一直返回Unit

时间:2012-03-20 11:34:01

标签: scala while-loop

我有以下代码,但我无法让它工作。一旦我在一个案例中放置了一个while循环,它就会返回一个单位,无论我在括号内做什么改变。

case While(c, body) =>
    while (true) {
      eval(Num(1))
    }
}

如何使while循环返回非Unit类型?

我试过了adding brackets around my while condition,但它仍然没有做到它应该做的事情。

任何指针?

更新

更多的背景信息,因为我没有真正解释代码应该做什么,如果我想获得一些帮助,这似乎很方便;

我已经定义了eval(exp : Exp)。这将评估一个功能。 Exp是一个抽象类。由几个类扩展,如PlusMinus(几个基本操作)和IfThenElse(cond : Exp, then : Exp, else : Exp)。最后但并非最不重要的是,While(cond: Exp, body: Exp)

如何使用它的例子;

eval(Plus(Num(1),Num(4))会产生NumValue(5)。 (Num(v:Value)的评估结果为NumValue(v).NumValue扩展了Value,这是另一个抽象类。)

eval(While(Lt(Num(1),Var("n")), Plus(Num(1), Var("n"))))

Lt(a : Exp, b : Exp)如果< NumValue(1)则返回{{1}}湾

4 个答案:

答案 0 :(得分:8)

您希望此循环返回哪个迭代?如果您想要Seq所有迭代的结果,请使用for表达式(也称为for理解)。如果您只想要最后一个,请在循环外创建var,在每次迭代时设置其值,并在循环后返回var。 (另请参阅其他循环结构,这些结构在不同类型的集合中实现为函数,例如foldLeftfoldRight,就返回值而言,它们有自己有趣的行为。)Scala {{1循环返回while,因为没有明智的一个大小适合这个问题的所有答案。

(顺便说一句,编译器无法知道这一点,但你编写的循环永远不会返回。如果编译器理论上足够聪明,可以发现Unit永远不会终止,那么预期返回类型为while(true)。)

答案 1 :(得分:8)

从其他答案中可以清楚地看到,Scala while循环始终返回Unit。 Scala的优点在于,如果它不能满足您的需求,您可以随时扩展它。

这是一个类似while的构造的定义,它返回最后一次迭代的结果(如果永远不输入循环,它会抛出异常):

def whiley[T](cond : =>Boolean)(body : =>T) : T = {
  @scala.annotation.tailrec
  def loop(previous : T) : T = if(cond) loop(body) else previous
  if(cond) loop(body) else throw new Exception("Loop must be entered at least once.")
}

...然后您可以将其用作while。 (实际上,@tailrec注释会使其编译成与while循环完全相同的东西。)

var x = 10
val atExit = whiley(x > 0) {
  val squared = x * x
  println(x)
  x -= 1
  squared
}
println("The last time x was printed, its square was : " + atExit)

(请注意,我并未声明该构造有用。)

答案 2 :(得分:7)

while循环的唯一目的是执行副作用。换句话说,它总是会评估为 Unit

如果你想要一些有意义的东西,为什么不考虑使用if-else-expression或for-expression?

答案 3 :(得分:2)

正如其他人和他们的母亲所说,虽然循环不会在Scala中返回值。似乎没有人提到的是,有一个原因:表现。

返回一个值会对性能产生影响,因此编译器必须在需要返回值时明智,而不是。有些情况可以轻而易举地完成,但也有复杂的情况。编译器必须更智能,这意味着它会更慢,更复杂。这笔费用被认为不值得。

现在,Scala中有两个循环结构(所有其他基于这两个):while循环和递归。 Scala可以优化尾递归,结果通常比while循环更快。或者,否则,您可以使用while循环并通过副作用返回结果。