问题
I occasionally come across the following pattern, where I essentially have a PartialFunction[SomeType,AnotherType]
, and want to treat it as a Function[SomeType,Option[AnotherType]
, eg:
def f(s:SomeType):Option[AnotherType] = s match {
case s1:SubType1 => Some(AnotherType(s1.whatever))
case s2:SubType2 => Some(AnotherType(s2.whatever))
case _ => None
}
Is there a way to write the above function in a way that avoids the default case and wrapping the result in Some
where it's defined? The best I've come up with so far is this:
def f(s:SomeType):Option[AnotherType] = pf.lift(s)
def pf:PartialFunction[SomeType,AnotherType] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}
Is there a way to do it without defining an intermediate function? I've already tried various things along the lines of the following, but haven't got anything to compile yet:
def f:Function[SomeType,Option[AnotherType]] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}.lift
回答1:
condOpt
in object scala.PartialFunction. From the scaladoc:
def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }
回答2:
Not so much an answer, as an explanation of why huynhjl's answer is correct...
Part of your confusion is that you're trying to def
a partial function. All this does is to create a method that returns a PartialFunction
object, when you may as well create the thing directly:
val pf: PartialFunction[SomeType,AnotherType] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}
Though I personally prefer to use type ascription:
val pf = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]
Either way, you have to specify what the input type is, so you have to give the exact signature of the PartialFunction
. I know it feels like it should be possible to to infer this but, alas, that is sadly not the case!
Using the ascribed version, you can then define and lift all in the same place:
val pf = ({
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]).lift
PartialFunction.condOpt
is the better solution though, as it allows the inferencer to do most of this work for you, leaving much cleaner code :)
来源:https://stackoverflow.com/questions/4721391/is-there-a-nicer-way-of-lifting-a-partialfunction-in-scala