2009-12-15 17 views
19

Finché abbiamo un PartialFunction[X,R] è molto facile convertirlo in una funzione che restituisce Option[R], ad es.Come convertire X => Opzione [R] in PartialFunction [X, R]

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

Tuttavia, che cosa se il compito è opposto: supponiamo di avere una funzione f ottenere X come argomento e tornare Option[R] di conseguenza. E voglio fare un PartialFunction[X,R] fuori di esso. Qual è il modo migliore?

Quello che è venuta in mente sembra piuttosto brutta per i miei gusti:

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

C'è qualche modo migliore che ho perso?

+0

possibile duplicato di [Inversa di metodo di sollevamento di funzione parziale] (http://stackoverflow.com/questions/5902266/inverse-of-partialfunctions-lift-method) –

+0

@ToddOwen Sono solo curioso quanto "prima" significa tu nella frase "questa domanda è stata fatta prima". Si prega di confrontare semplicemente le date di entrambe le domande. –

+0

Chiudi voto ritirato. Scusate, non era una questione di "prima", ma piuttosto il fatto che l'altra domanda sembrava aver ricevuto una risposta migliore (con 28 voti). Ma ora noto che Thayne ha dato la stessa risposta qui. –

risposta

27

So che questo è un vecchio thread, ma se qualcun altro si imbatte in questo, Function.unlift fa esattamente questo.

12

ne dite di questo:

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 !! A quanto pare ho bisogno di resettare il mio cervello in qualche modo :) Molte grazie! –

+1

Questo dovrebbe essere fornito come una conversione implicita in 'Predef' – HRJ

5

Suppongo che si possa ignorare applicare e isDefinedAt a mano, ma lo farei il modo in cui si trova brutto.

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

Quindi, ancora una volta, penso che preferisco sovrascrivere' apply' e 'isDefinedAt' dopo tutto. –

+0

Grazie! Anche se ora ho l'impressione che la necessità di scrivere questo codice di "conversione" mi segnali qualche problema, quindi sto cercando di riflettere più a fondo. Il minimo problema che vedo 'f (x)' sarà chiamato due volte (nel caso di 'Some') in qualsiasi implementazione. –

+0

Sì, viene chiamato due volte. È possibile memorizzare nella cache il risultato, ma ciò sarebbe imbarazzante, e non proprio ciò che accade in una funzione parziale. –

Problemi correlati