Цель выражения "return" в Scala?

Есть ли настоящая причина предоставления оператора return в Scala? (кроме того, что они более "совместимы с Java" )

Ответы

Ответ 1

Игнорируя вложенные функции, всегда можно заменить вычисления Scala на возврат с эквивалентными вычислениями без возврата. Этот результат восходит к началу "структурированного программирования" и называется структурированной программной теоремой, достаточно умно.

С вложенными функциями ситуация меняется. Scala позволяет помещать "возвращаемую" глубину в глубину внутри вложенных функций. Когда возврат выполняется, управление выпрыгивает из всех вложенных функций в самый внутренний содержащий метод, из которого он возвращается (при условии, что метод на самом деле все еще выполняется, в противном случае создается исключение). Такой тип разворачивания стека может быть выполнен с исключениями, но не может быть выполнен путем механической перестройки вычисления (как это возможно без вложенных функций).

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

for(i<- 1 to bezillion; j <- i to bezillion+6){
if(expensiveCalculation(i, j)){
   return otherExpensiveCalculation(i, j)
}

withExpensiveResource(urlForExpensiveResource){ resource =>
// do a bunch of stuff
if(done) return
//do a bunch of other stuff
if(reallyDoneThisTime) return
//final batch of stuff
}

Ответ 2

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

Хотя это, безусловно, так, как говорит Дэйв Гриффит, что вы можете устранить любое использование return, часто бывает более обманчивым, чтобы просто сократить короткое сокращение с помощью открытого return.

Также помните, что return возвращает методы, а не функции (литералы), которые могут быть определены внутри метода.

Ответ 3

Вот пример

В этом методе есть много операторов if-else для управления потоком, потому что нет возврата (это то, с чем я пришел, вы можете использовать свое воображение для его расширения). Я взял это из примера реальной жизни и модифицировал его как фиктивный код (на самом деле он длиннее этого):

Без возврата:

 def process(request: Request[RawBuffer]): Result = {
      if (condition1) {
        error()
      } else {
        val condition2 = doSomethingElse()
        if (!condition2) {
          error()
        } else {
          val reply = doAnotherThing()
          if (reply == null) {
            Logger.warn("Receipt is null. Send bad request")
            BadRequest("Coudln't receive receipt")
          } else {
            reply.hede = initializeHede()
            if (reply.hede.isGood) {
              success()
            } else {
              error()
            }
          }
        }
      }
  }

С возвращением:

  def process(request: Request[RawBuffer]): Result = {
      if (condition1) {
        return error()
      }

      val condition2 = doSomethingElse()
      if (!condition2) {
        return error()
      }

      val reply = doAnotherThing()

      if (reply == null) {
        Logger.warn("Receipt is null. Send bad request")
        return BadRequest("Coudln't receive receipt")
      }

      reply.hede = initializeHede()
      if (reply.hede.isGood)
        return success()

      return error()
  }

В моих глазах второй - более читаемый и даже управляемый, чем первый. Глубина углубления (с хорошо отформатированным кодом) идет глубоко и глубоко, если вы не используете оператор return. И мне это не нравится:)

Ответ 4

Я рассматриваю return как полезный при написании императивного кода стиля, который обычно означает код ввода-вывода. Если вы выполняете чистый функциональный код, вам не нужно (и не следует использовать) return. Но с функциональным кодом вам может понадобиться лень, чтобы получить производительность, эквивалентную императивному коду, который может "ускользнуть" с помощью return.