Scala while loop returns Unit all the time

北战南征 提交于 2020-01-15 03:13:29

问题


I have the following code, but I can't get it to work. As soon as I place a while loop inside the case, it's returning a unit, no matter what I change within the brackets.

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

How can I make this while loop return a non-Unit type?

I tried adding brackets around my while condition, but still it doesn't do what it's supposed to.

Any pointers?

Update

A little more background information since I didn't really explain what the code should do, which seems to be handy if I want to receive some help;

I have defined a eval(exp : Exp). This will evaluate a function. Exp is an abstract class. Extended by several classes like Plus, Minus (few more basic operations) and a IfThenElse(cond : Exp, then : Exp, else : Exp). Last but not least, there's the While(cond: Exp, body: Exp).

Example of how it should be used;

eval(Plus(Num(1),Num(4)) would result in NumValue(5). (Evaluation of Num(v : Value) results in NumValue(v). NumValue extends Value, which is another abstract class).

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

Lt(a : Exp, b : Exp) returns NumValue(1) if a < b.


回答1:


It's probably clear from the other answer that Scala while loops always return Unit. What's nice about Scala is that if it doesn't do what you want, you can always extend it.

Here is the definition of a while-like construct that returns the result of the last iteration (it will throw an exception if the loop is never entered):

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.")
}

...and you can then use it as a while. (In fact, the @tailrec annotation will make it compile into the exact same thing as a while loop.)

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)

(Note that I'm not claiming the construct is useful.)




回答2:


Which iteration would you expect this loop to return? If you want a Seq of the results of all iterations, use a for expression (also called for comprehension). If you want just the last one, create a var outside the loop, set its value on each iteration, and return that var after the loop. (Also look into other looping constructs that are implemented as functions on different types of collections, like foldLeft and foldRight, which have their own interesting behaviors as far as return value goes.) The Scala while loop returns Unit because there's no sensible one size fits all answer to this question.

(By the way, there's no way for the compiler to know this, but the loop you wrote will never return. If the compiler could theoretically be smart enough to figure out that while(true) never terminates, then the expected return type would be Nothing.)




回答3:


The only purpose of a while loop is to execute a side-effect. Or put another way, it will always evaluate to Unit.

If you want something meaningful back, why don't you consider using an if-else-expression or a for-expression?




回答4:


As everyone else and their mothers said, while loops do not return values in Scala. What no one seems to have mentioned is that there's a reason for that: performance.

Returning a value has an impact on performance, so the compiler would have to be smart about when you do need that return value, and when you don't. There are cases where that can be trivially done, but there are complex cases as well. The compiler would have to be smarter, which means it would be slower and more complex. The cost was deemed not worth the benefit.

Now, there are two looping constructs in Scala (all the others are based on these two): while loops and recursion. Scala can optimize tail recursion, and the result is often faster than while loops. Or, otherwise, you can use while loops and get the result back through side effects.



来源:https://stackoverflow.com/questions/9785965/scala-while-loop-returns-unit-all-the-time

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!