Why not all defs that return an Option can be placed in pattern matching

What is special about unapply? If a definition has a single argument signature that returns an Option, why can’t I use it directly in pattern matching? Why is wrapping it in an object and calling it unapply a better approach?

I have an old workaround (which might be sufficient) and some quick thoughts.

In Scala 2, it seems you needed to support the unapply scheme, so that extractors could be defined at the top-level. That argument disappears in Scala 3, but changing scheme is costly, and supporting both schemes requires dealing with some ambiguity.

As a workaround, to turn a definition into an unapply extractor, you can call a helper method.

I wrote one version in 2014, and IIRC others did too — this wasn’t in the stdlib back then (not sure now).
And I don’t recall if this works for unapplySeq — I didn’t do it back then.

Example uses:

Note the extractors are defined outside the match, since patterns can’t contain extractor expressions (and that’s probably a good idea).

Generic helper definition:

See also: the Extractor.scala library, and SIP-NN - CONVERTERS AMONG OPTIONAL FUNCTIONS, PARTIALFUNCTIONS AND EXTRACTOR OBJECTS.

By the way, despite looking like a not-yet-considered SIP this is actually part of Scala 2.13:

scala> val digit = (_: String).toIntOption
val digit: String => Option[Int] = $Lambda$6369/1271707143@78dfebff

scala> "42" match { case digit.unlift(d) => d }
val res6: Int = 42

The scaladoc contains a table for how to convert between partial functions, option returning functions and extractors.

1 Like