Est-il un moyen de plus agréable de soulever une fonction partielle à Scala?
-
12-10-2019 - |
Question
Je viens de temps en temps à travers le schéma suivant, où j'ai essentiellement un PartialFunction[SomeType,AnotherType]
, et que vous voulez le traiter comme un Function[SomeType,Option[AnotherType]
, par exemple:
def f(s:SomeType):Option[AnotherType] = s match {
case s1:SubType1 => Some(AnotherType(s1.whatever))
case s2:SubType2 => Some(AnotherType(s2.whatever))
case _ => None
}
Est-il possible d'écrire la fonction ci-dessus d'une manière qui évite le cas par défaut et envelopper le résultat dans Some
où il est défini? Le meilleur que je suis venu avec à ce jour est la suivante:
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)
}
Est-il possible de le faire sans définir une fonction intermédiaire? Je l'ai déjà essayé différentes choses le long des lignes de ce qui suit, mais n'ai rien à compiler encore:
def f:Function[SomeType,Option[AnotherType]] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}.lift
La solution
condOpt
dans scala.PartialFunction d'objet. De l'scaladoc:
def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }
Autres conseils
Pas tellement une réponse, comme une explication des raisons pour lesquelles la réponse de huynhjl est correcte ...
Une partie de votre confusion est que vous essayez de def
une fonction partielle. Tout cela fait est de créer une méthode qui retourne un objet PartialFunction
, lorsque vous pouvez ainsi créer directement la chose:
val pf: PartialFunction[SomeType,AnotherType] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}
Bien que je préfère personnellement utiliser le type ascription:
val pf = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]
De toute façon, vous devez spécifier ce type d'entrée est, donc vous devez donner la signature exacte du PartialFunction
. Je sais qu'il se sent comme il devrait être possible de déduire cela, mais, hélas, qui est malheureusement pas le cas!
En utilisant la version attribuée, vous pouvez définir et soulever tout au même endroit:
val pf = ({
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]).lift
PartialFunction.condOpt
est la meilleure solution si, car il permet au inferencer de faire plus de ce travail pour vous, en laissant beaucoup de code de nettoyage:)