我有以下代码,但我无法让它工作。一旦我在一个案例中放置了一个while循环,它就会返回一个单位,无论我在括号内做什么改变。
case While(c, body) =>
while (true) {
eval(Num(1))
}
}
如何使while循环返回非Unit类型?
我试过了adding brackets around my while condition,但它仍然没有做到它应该做的事情。
任何指针?
更新
更多的背景信息,因为我没有真正解释代码应该做什么,如果我想获得一些帮助,这似乎很方便;
我已经定义了eval(exp : Exp)
。这将评估一个功能。
Exp
是一个抽象类。由几个类扩展,如Plus
,Minus
(几个基本操作)和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}}湾
答案 0 :(得分:8)
您希望此循环返回哪个迭代?如果您想要Seq
所有迭代的结果,请使用for
表达式(也称为for
理解)。如果您只想要最后一个,请在循环外创建var
,在每次迭代时设置其值,并在循环后返回var
。 (另请参阅其他循环结构,这些结构在不同类型的集合中实现为函数,例如foldLeft
和foldRight
,就返回值而言,它们有自己有趣的行为。)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循环并通过副作用返回结果。