I have a method that receives a function, but that function may be partial, in such case I don't want it to fail with MatchError.
def doSomething[X,Y](opt:Option[X])(f:X=>Y)={
f match {
case p:PartialFunction[X,Y]=> opt.flatMap(p.lift) //This doesn't seem to work
case _ => opt.map(f)
}
}
That way I can use the method like this
doSomething(x){
case t if predicate(t) => otherMethod(t)
}
so in case I don't have a predicate, I can use it like
this doSomething(x)(otherMethod)
instead of
doSoemthing(x){
case t=> otherMethod(t)
}
Note: Looking for a solution that doesn't require catching MatchError
exceptions
The syntax for partial function has been changed since 2.9 per SLS 8.5, so that even you do { case x => y}
, it DOES NOT mean it is a partial function. Its type will be exact as you define it as.
In your case, you defined it as X=>Y
(as in your function parameter), so it is just a X=>Y
(it got compiled into a regular function, and non match cases will throw MatchError), and even you do isInstanceOf[PartialFunciton[_,_]]
, it won't match.
To make your scenario work, you can just simply cast the passed function as PartialFunction, like:
doSomething(Some(1))({case 2 => 0}: PartialFunction[Int,Int]) //This returns None without MatchError
while
doSomething(Some(1)){case 2 => 0} //This gives MatchError and it is not recognized as PartialFunction inside the body
This is probably not as convenient as you thought it is, but it is the only way to make it work. (or you define 2 separate functions for either case, like collect
and map
in standard library)