2011-01-18 1 views
3

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:Existe-t-il une meilleure façon de lever une fonction partielle dans Scala?

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 la cas par défaut et envelopper le résultat dans Some où il est défini? Le meilleur que j'ai trouvé jusqu'ici est le suivant:

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) 
} 

Y a-t-il un moyen 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 
+0

Que voulez-vous dire par fonction intermédiaire? – Raphael

+0

@Raphael Une fonction littérale n'est pas une fonction littérale partielle, à moins qu'il n'y ait des indications de type indiquant le contraire. –

+0

Ah, "j'ai" signifie "je code", pas "j'ai une valeur de type". Malentendu, désolé. – Raphael

Répondre

6

condOpt dans scala.PartialFunction objet. De l'scaladoc:

def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x } 
+0

Mais 'condOpt (x) (pf)' est équivalent à 'pf.lift (x)'. Est-ce que je manque quelque chose? Ou est le point que vous pouvez utiliser une fonction littérale ici sans annotations de type explicites? –

+0

@oxbow_lakes, je ne peux pas parler pour Kristian et je ne pensais pas trop à la question ou à ma réponse, 'condOpt' semblait juste pertinent à ce qu'il demandait. – huynhjl

+0

En effet, j'aime le fait que condOpt infère les types. –

4

Pas tellement une réponse, comme une explication des raisons pour lesquelles la réponse est correcte huynhjl ...

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 la chose directement:

val pf: PartialFunction[SomeType,AnotherType] = { 
    case s1:SubType1 => AnotherType(s1.whatever) 
    case s2:SubType2 => AnotherType(s2.whatever) 
} 

Bien que je préfère 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 quel est le type d'entrée, donc vous devez donner la signature exacte du PartialFunction. Je sais qu'il devrait être possible de déduire cela mais, hélas, ce n'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 mais, car il permet au inferencer de faire plus de ce travail pour vous, en laissant code beaucoup plus propre :)

+0

C'est exactement ce que je fais aussi quand j'ai besoin du même comportement: c'est dommage que 'condOpt' soit un nom de méthode aussi affreux. J'utiliserais ça à la place. Pourquoi ils ne l'ont pas appelé 'applyLifted' je ne sais pas! –

+0

Ce n'est pas exactement le nom le plus intuitif au monde, n'est-ce pas? –

+0

Merci Kevin, je pensais que j'avais aussi essayé Val, mais ça devait être une mauvaise incantation. Votre réponse est certainement dans le sens du chemin que je descendais, mais j'ai accepté huynhjl comme c'était plus ce que je cherchais (malgré le nom de la fonction!) –

Questions connexes