Цикл Scala while возвращает Unit все время - PullRequest
2 голосов
/ 20 марта 2012

У меня есть следующий код, но я не могу заставить его работать.Как только я помещаю цикл while внутрь корпуса, он возвращает единицу, независимо от того, что я изменяю в скобках.

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

Как я могу сделать так, чтобы цикл while возвращал тип не Unit?

Я пытался добавить скобки вокруг моего условия while , но все равно он не выполняет то, что должен.

Есть указатели?

Обновление

Немного дополнительной справочной информации, поскольку я действительно не объяснил, что должен делать код, что представляется полезным, если я хочу получить некоторую помощь;

Я определил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), если a

Ответы [ 4 ]

8 голосов
/ 20 марта 2012

Из другого ответа, вероятно, ясно, что циклы 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)

(Обратите внимание, что я не утверждаю, что конструкция полезна.)

8 голосов
/ 20 марта 2012

Какую итерацию вы ожидаете от этого цикла? Если вы хотите Seq результатов всех итераций, используйте выражение for (также называемое for понимание). Если вам нужен только последний, создайте var вне цикла, устанавливайте его значение на каждой итерации и возвращайте var после цикла. (Также обратите внимание на другие циклические конструкции, которые реализованы как функции в различных типах коллекций, таких как foldLeft и foldRight, которые имеют свои собственные интересные поведения в отношении возвращаемого значения.) Цикл Scala while возвращает Unit потому что нет разумного единого размера, который бы подходил всем ответам на этот вопрос.

(Между прочим, компилятору нет возможности узнать это, но написанный вами цикл никогда не вернется. Если компилятор теоретически может быть достаточно умным, чтобы выяснить, что while(true) никогда не завершается, то ожидаемый тип возвращаемого значения будет Nothing.)

7 голосов
/ 20 марта 2012

Единственная цель цикла while - выполнить побочный эффект.Или, другими словами, он всегда будет иметь значение Unit .

Если вы хотите вернуть что-то значимое, почему бы вам не рассмотреть возможность использования выражения if-else или for-expression?

2 голосов
/ 20 марта 2012

Как говорили все остальные и их матери, циклы пока не возвращают значения в Scala.Кажется, что никто не упомянул, что для этого есть причина: производительность.

Возвращение значения влияет на производительность, поэтому компилятор должен быть умным, когда вам нужно это возвращаемое значение, икогда ты неЕсть случаи, когда это можно сделать тривиально, но есть и сложные случаи.Компилятор должен быть умнее, а значит, он будет медленнее и сложнее.Считалось, что стоимость не стоит выгоды.

Теперь в Scala есть две циклические конструкции (все остальные основаны на этих двух): циклы while и рекурсия.Scala может оптимизировать хвостовую рекурсию, и результат часто быстрее, чем циклы while.Или, в противном случае, вы можете использовать циклы while и получить результат обратно через побочные эффекты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...