What is the reasoning for the imbalance of Scala's regular value assignment vs extractor assignment?

60 Views Asked by At

Scala appears to have different semantics for regular value assignment versus assignment during an extraction. This has created some very subtle runtime bugs for me as my codebase has migrated over time.

To illustrate:

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

I don't see why the two val assignment lines would be imbalanced with regard to compile/runtime behavior.

Some I am curious: Is there a reason for this behavior? Is it an undesirable artifact of the way the extraction is implemented?

(tested in Scala 2.11.7)

1

There are 1 best solutions below

6
On

Yes, there is.

In the case of an extractor you are specifying a pattern that you expect to match at this position. This is translated to a call of an extractor method from Any to Option[String] and this method can be called with the value of type AnyRef you provide. You are just asserting, that you do indeed get a result and not "None".

In the other line you are using a type annotation, i.e. you are specifying the type of "f" explicitly. But then you are assigning an incompatible value.

Of course the compiler could add implicit type casts but making type casts so easy would not really suit a language like Scala.

You should also keep in mind that extractors have nothing to do with types. In the Pattern Foo(x) the name Foo has nothing to do with the type Foo. It is just the Name of an extractor method.

Using patterns in this way is of course a quite dynamic feature, but I think it is intentional.