В чем причина дисбаланса регулярного присвоения значений Scala и присвоения экстрактора?

Кажется, что в Scala семантика для обычного присваивания значений отличается от присваивания во время извлечения. Это создало некоторые очень тонкие ошибки во время выполнения для меня, так как моя кодовая база мигрировала со временем.

Проиллюстрировать:

case class Foo(s: String)

def anyRef(): AnyRef = { ... }

val Foo(x) = anyRef() // compiles but throws exception if anyRef() is not a Foo

val f: Foo = anyRef() // does not compile

Я не понимаю, почему два val Строки присваивания будут несбалансированными в отношении поведения во время компиляции / выполнения.

Некоторым мне любопытно: есть ли причина для такого поведения? Является ли это нежелательным артефактом способа извлечения?

(протестировано в Scala 2.11.7)

1 ответ

Да, есть.

В случае экстрактора вы указываете шаблон, который вы ожидаете, чтобы соответствовать в этой позиции. Это переводится в вызов метода экстрактора из Any в Option[String], и этот метод может вызываться со значением типа AnyRef, который вы предоставляете. Вы просто утверждаете, что вы действительно получаете результат, а не "Нет".

В другой строке вы используете аннотацию типа, т.е. вы явно указываете тип "f". Но тогда вы присваиваете несовместимое значение.

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

Также следует помнить, что экстракторы не имеют ничего общего с типами. В Узор Foo(x) имя Foo не имеет ничего общего с типом Foo. Это просто имя метода экстрактора.

Использование шаблонов таким образом, конечно, довольно динамичная особенность, но я думаю, что это намеренно.

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