Вывод типа по типу возврата метода
Почему 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)
}
Ответы
Ответ 1
Возвращаемым типом метода является либо тип последнего оператора в блоке, который его определяет, либо тип выражения, определяющего его, в отсутствие блока.
Когда вы используете return
внутри метода, вы вводите другое утверждение, из которого метод может вернуться. Это означает, что Scala не может определить тип этого return
в найденной точке. Вместо этого он должен действовать до конца метода, а затем объединить все точки выхода для вывода их типов, а затем вернуться к каждой из этих точек выхода и назначить их типы.
Чтобы сделать это, это увеличит сложность компилятора и замедлит его, для единственного усиления отсутствия необходимости указывать тип возвращаемого значения при использовании return
. В настоящей системе, с другой стороны, вывод возвращаемого типа происходит бесплатно от вывода ограниченного типа Scala уже использует.
Итак, в итоге, в балансе между сложностью компилятора и коэффициентами прибыли, последний считался неценным первым.
Ответ 2
Это увеличит сложность компилятора (и языка). Это просто на самом деле фанк, чтобы делать вывод типа на что-то подобное. Как и в случае с любым типом вывода, все работает лучше, когда у вас есть одно выражение. Рассеянные операторы return эффективно создают много неявного ветвления, которое становится очень липким для унификации. Это не то, что это особенно сложно, просто липкое. Например:
def foo(xs: List[Int]) = xs map { i => return i; i }
Что, я прошу вас, делает ли компилятор здесь? Если компилятор делал вывод с явными операторами return, это должно быть Any
. Фактически, многие методы с явными операторами return вернут Any
, даже если вы не получите подлый результат с нелокальными возвращениями. Как я сказал, липкий.
И кроме того, это не язык, который следует поощрять. Явные возвращения не улучшают ясность кода, если только один явный возврат и что в конце функции. Причина довольно проста в том, что вы просматриваете пути кода как ориентированный граф. Как я сказал ранее, разбросанные возвраты производят много неявного разветвления, которое производит странные листья на вашем графике, а также множество дополнительных путей в основном теле. Это просто фанки. Поток управления намного проще увидеть, являются ли ваши ветки явными (соответствие шаблону или выражения if
), и ваш код будет намного более функциональным, если вы не будете полагаться на побочные эффекты return
для создания значений.
Итак, как и некоторые другие "обескураженные" функции в Scala (например, asInstanceOf
, а не as
), разработчики языка сделали преднамеренный выбор, чтобы сделать вещи менее приятными. Это в сочетании со сложностью, которую она вводит в вывод типа и практическую бесполезность результатов во всех, кроме самых надуманных сценариев. Для скаляра просто не имеет смысла пытаться сделать такой вывод.
Мораль истории: научись не разбрасывать свои возвращения! Это хороший совет на любом языке, а не только Scala.
Ответ 3
Учитывая это (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
... кажется, это не случайно.
Ответ 4
Я не уверен, почему. Возможно, просто препятствовать использованию инструкции return
.:)