Вывод типа по типу возврата метода

Почему Scala не может определить тип возврата метода, когда есть явный return оператор используется в методе?

Например, почему следующий код компилируется?

object Main {
    def who = 5
    def main(args: Array[String]) = println(who)
}

Но следующее не делает.

object Main {
    def who = return 5
    def main(args: Array[String]) = println(who)
}

4 ответа

Решение

Тип возврата метода - это либо тип последнего оператора в блоке, который его определяет, либо тип выражения, которое его определяет, в отсутствие блока.

Когда вы используете return внутри метода вы вводите другой оператор, из которого метод может возвращаться. Это означает, что Scala не может определить тип этого return в точке, где это найдено. Вместо этого он должен продолжаться до конца метода, затем объединить все точки выхода для определения их типов, а затем вернуться к каждой из этих точек выхода и назначить их типы.

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

Таким образом, в конечном итоге, в балансе между сложностью компилятора и полученными преимуществами, последний считается не стоящим первого.

Это увеличило бы сложность компилятора (и языка). Просто очень интересно делать вывод типа на что-то подобное. Как и в случае с любым типом, связанным с выводом, все работает лучше, когда у вас есть одно выражение. Разбросанные операторы возврата эффективно создают множество неявных ветвлений, которые очень трудно объединить. Дело не в том, что это особенно сложно, просто липкое. Например:

def foo(xs: List[Int]) = xs map { i => return i; i }

Что, я спрашиваю, компилятор выводит здесь? Если бы компилятор делал вывод с явными инструкциями возврата, он должен был бы быть Any, На самом деле, многие методы с явными операторами возврата в конечном итоге возвращают Any, даже если вы не получаете подлый с нелокальными возвратами. Как я уже сказал, липкий.

И, кроме того, это не языковая функция, которую следует поощрять. Явные возвраты не улучшают ясность кода, если нет только одного явного возврата в конце функции. Причину довольно легко понять, если вы рассматриваете пути кода как ориентированный граф. Как я уже говорил ранее, рассеянные возвраты создают много неявных ветвлений, которые создают странные листья на вашем графике, а также много дополнительных путей в основном теле. Это просто прикольно. Поток управления намного легче увидеть, если все ваши ветви явные (сопоставление с образцом или if выражения), и ваш код будет гораздо более функциональным, если вы не полагаетесь на побочные эффекты return заявления для производства ценностей.

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

Мораль истории: учись не разбрасывать свои доходы! Это хороший совет на любом языке, не только Scala.

Учитывая это (2.8.Beta1):

object Main {
  def who = return 5
  def main(args: Array[String]) = println(who)
}
<console>:5: error: method who has return statement; needs result type
         def who = return 5

... кажется, не случайно.

Я не уверен почему. Возможно, просто чтобы препятствовать использованию return заявление.:)

Другие вопросы по тегам