Цель «обратного» высказывания в Scala? - PullRequest
30 голосов
/ 22 сентября 2010

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

Ответы [ 4 ]

47 голосов
/ 22 сентября 2010

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

С вложенными функциями ситуация меняется. 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
}
26 голосов
/ 22 сентября 2010

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

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

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

4 голосов
/ 30 октября 2015

Вот пример

Этот метод имеет множество операторов 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. И мне это не нравится :)

2 голосов
/ 23 сентября 2010

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

...