I do not understand why using a variable for a temporary value makes the partial function different:
val f1: PartialFunction[Option[Int], Int] = { b =>
val i = identity(b)
i match {
case Some(res) => res
}
}
val f2: PartialFunction[Option[Int], Int] = { b =>
identity(b) match {
case Some(res) => res
}
}
f1.isDefinedAt(None)
f2.isDefinedAt(None)
The result is true
/ false
with Scala 2.13.12 and Scala 3.3.1. The first version shows match exhaustivity warning, the second one does not. The code does not compile with Scala 2.12.18, error is in the first version:
type mismatch;
found : Option[Int] => Int
required: PartialFunction[Option[Int],Int]
How is the second version more "partial" than the first one?
I think the language specification answers this:
https://www.scala-lang.org/files/archive/spec/3.4/06-expressions.html
When a
PartialFunction
is required, an additional memberisDefinedAt
is synthesized, which simply returns true. However, if the function literal has the shapex => x match { $...$ }
, thenisDefinedAt
is derived from the pattern match in the following way: each case from the match expression evaluates totrue
, and if there is no default case, a default case is added that evaluates tofalse
.
The first versions does not have the expected shape for a special case conversion of a Single Abstact Method to a partial function, therefore a normal (total) function is created which is later converted to a partial function.
Maybe requiring partial functions to be written as a Pattern Matching Anonymous Function would be less confusing, but I guess there is some reason or history behind this.