Вывод типа по типу возврата метода
Почему 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
заявление.:)