Подтвердить что ты не робот

Разный вывод типа для `def` и` val` в Scala

Я заметил разницу в выводе типа Scala при применении к def и val.

Используя def, я могу определить абстрактный нулевой метод const, возвращающий некоторое значение типа Int => Int. При реализации const с литералом функции мне не нужно указывать тип параметра, поскольку он может быть выведен компилятором:

trait D {
  def const: Int => Int
}
object D extends D {
  def const = i => i + 1
}

Это нормально. (С другой стороны, создается новый экземпляр функции для каждого доступа к D.const.)

Теперь рассмотрим аналогичную конструкцию с использованием val:

trait V {
  val const: Int => Int
}
object V extends V {
  val const = i => i + 1
}

Это не будет компилироваться, не с помощью

error: missing parameter type
   val const = i => i + 1
               ^

Почему?

4b9b3361

Ответ 1

Как и в случае Scala 2.9.1, это "как указано". Ссылаясь на Мартина Одерского из SI-2742:

Для методов возвращаемые типы в унаследованных абстрактных методах берутся как ожидаемый тип правой стороны. Для значений нет такого правила. Так что это будет запрос улучшения спецификации, как я вижу.

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

Ответ 2

Если вы создадите этот код с параметром -Xprint all, вы увидите, что:

abstract trait V extends scala.AnyRef {   
<stable> <accessor> def const: Int => Int
};

final object V extends java.lang.Object with V with ScalaObject {

def this(): object V = {
  V.super.this();
  ()
};

private[this] val const: <error> => <error> = ((i: <error>) => i.+(1));
<stable> <accessor> def const: <error> => <error> = V.this.const
}

Таким образом, ошибка возникает при создании private val и accessor. й компилятор попытается оценить значение, зависящее от val const, прежде чем создать accessor def const.

если вы посмотрите на val const, определенный в признаке, вы увидите, что создание private val было отключено, потому что это только определение для Access-доступа def.

Я думаю, что тип вывода с предыдущим определением (в признаке или суперклассе) произошел только тогда, когда он попытался создать аксессор, а не для оценки значения.

И для последнего def const тип основан только на private [this] val const type: error = > error