Reputation: 5350
I defined 2 versions of PartialFunction
in Scala.
val doubleEvens1: PartialFunction[Int, Int] = {
case x if x % 2 == 0 => x * 2
}
val doubleEvens2 = new PartialFunction[Int, Int] {
override def isDefinedAt(x: Int): Boolean = x % 2 == 0
override def apply(v1: Int): Int = v1 * 2
}
and a list:
val list = List(1, 2, 3, 4, 5)
However their behaviors diff for undefined values:
// doubleEvens1
println(doubleEvens1.isDefinedAt(3)) // false
println(list.collect(doubleEvens1)) // List(4, 8)
println(doubleEvens1(3)) // scala.MatchError
println(list.map(doubleEvens1)) // scala.MatchError
// doubleEvens2
println(doubleEvens2.isDefinedAt(3)) // false
println(list.collect(doubleEvens2)) // List(4, 8)
println(doubleEvens2(3)) // 6
println(list.map(doubleEvens2)) // List(2, 4, 6, 8, 10)
I guess doubleEvens1
should be reasonable since it accords with the mathematical definition. But is the behavior of doubleEvens2
designed by purpose? Or am I missing something in the code snippet?
Upvotes: 4
Views: 291
Reputation: 67280
If you implement your own apply
method and do not check against isDefinedAt
, then obviously you can call that method with any input without an exception being thrown. This is explicitly stated in the docs:
It is the responsibility of the caller to call
isDefinedAt
before callingapply
, because ifisDefinedAt
is false, it is not guaranteedapply
will throw an exception to indicate an error condition. If an exception is not thrown, evaluation may result in an arbitrary value.
It just so happens that the partial function created from a pattern match will call isDefinedAt
itself from its apply
method implementation and throw an exception.
So if you want to copy that behaviour, you have to do this:
val doubleEvens2 = new PartialFunction[Int, Int] {
override def isDefinedAt(x: Int): Boolean = x % 2 == 0
override def apply(x: Int): Int =
if (isDefinedAt(x)) x * 2 else throw new MatchError(x.toString)
}
The drawback of course is that some code (isDefined
) might be invoked multiple times, as discussed in this question.
Upvotes: 6