2009-12-15 13 views
19

Solange wir eine PartialFunction[X,R] haben, ist es sehr einfach, es in eine Funktion zu konvertieren, die Option[R], z.Wie konvertiert man X => Option [R] zu PartialFunction [X, R]

def pfToOptf[X, R](f: PartialFunction[X,R])(x: X) = 
    if (f.isDefinedAt(x)) Some(f(x)) 
    else None 

Was aber, wenn die Aufgabe Gegenteil ist: Angenommen, ich habe eine Funktion fX als Argument bekommen und Option[R] als Ergebnis zurück. Und ich möchte eine PartialFunction[X,R] daraus machen. Was ist der beste Weg?

Was ich mit Blicken ziemlich hässlich nach meinem Geschmack habe kommen:

def optfToPf[X,R](f: X => Option[R]) : PartialFunction[X,R] = { 
    object extractor { 
     def unapply(x: X): Option[R] = f(x) 
    } 

    { case extractor(r) => r } 
} 

Gibt es einen besseren Weg, ich verpasst?

+0

möglich Duplikat von [Inverse of PartialFunction der Lift-Methode] (http://StackOverflow.com/Questions/5902266/Inverse-of-PartialFunctionsLift-Method) –

+0

@ToddOwen Ich bin nur neugierig, was "vor" bedeutet zu Sie in dem Satz "diese Frage wurde zuvor gestellt". Bitte vergleichen Sie einfach die Daten beider Fragen. –

+0

Enge Abstimmung zurückgezogen. Entschuldigung, es ging nicht um "vorher", sondern eher darum, dass die andere Frage (mit 28 Stimmen) besser beantwortet zu sein schien. Aber jetzt merke ich, dass Thayne die gleiche Antwort gegeben hat. –

Antwort

27

Ich weiß, das ein alter Thread, aber wenn jemand anderes über diese kommt, Function.unlift tut genau dies.

12

Wie wäre es damit:

Welcome to Scala version 2.8.0.r19650-b20091114020153 (Java HotSpot(TM) Client VM, Java 1.6.0_17). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> def optfToPf[X,R](f: X => Option[R]): PartialFunction[X,R] = x => f(x) match { 
    |  case Some(r) => r 
    | } 
optfToPf: [X,R](f: (X) => Option[R])PartialFunction[X,R] 

scala> 
+0

Oh !! Anscheinend muss ich irgendwie mein Gehirn zurücksetzen :) Vielen Dank! –

+1

Dies sollte als eine implizite Umwandlung in 'Predef' – HRJ

5

Ich nehme an, Sie von Hand anwenden und isDefinedAt außer Kraft setzen könnte, aber ich würde es tun, so wie du hässlich finden.

def optfToPf[X,R](f: X => Option[R]) = new PartialFunction[X,R] { 
    def apply(x: X): R = f(x).get 
    def isDefinedAt(x: X): Boolean = f(x) != None 
} 

Testing:

scala> val map = Map(1 -> 2) 
map: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) 

scala> map(1) 
res0: Int = 2 

scala> def mapOpt(key: Int) = map.get(key) 
mapOpt: (key: Int)Option[Int] 

scala> mapOpt(1) 
res1: Option[Int] = Some(2) 

scala> mapOpt(2) 
res2: Option[Int] = None 

scala> val mapPf = optfToPf(mapOpt _) 
mapPf: java.lang.Object with PartialFunction[Int,Int] = <function1> 

scala> mapPf.isDefinedAt(2) 
res3: Boolean = false 

scala> mapPf.isDefinedAt(1) 
res4: Boolean = true 

scala> mapPf(1) 
res5: Int = 2 

scala> mapPf(2) 
java.util.NoSuchElementException: None.get 
+1

zur Verfügung gestellt werden Dann wiederum denke ich, dass ich lieber überschreiben' apply' und 'isDefinedAt' schließlich. –

+0

Danke! Obwohl ich jetzt unter Eindruck bin, dass die Notwendigkeit, diesen "Umwandlungs" -Code zu schreiben, mich über ein Problem signalisiert, so versuche ich, über gründlicher nachzudenken. Das kleinste Problem, das ich sehe, 'f (x)' wird zweimal aufgerufen (im Falle von 'Some') in irgendeiner Implementierung. –

+0

Ja, es wird zweimal aufgerufen. Sie könnten das Ergebnis zwischenspeichern, aber das wäre peinlich und nicht wirklich, was in einer Teilfunktion passiert. –