2009-12-15 63 views
19

只要我們有一個PartialFunction[X,R],就可以很容易地將它轉換爲返回Option[R]的函數。如何將X =>選項[R]轉換爲部分函數[X,R]

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

但是,如果有什麼任務是相反的:假設我有一個函數f越來越X作爲參數和返回Option[R]結果。而且我想製作一個PartialFunction[X,R]。什麼是最好的方法?

我想出看起來很醜陋,我的口味:

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

有沒有一些更好的辦法,我錯過了什麼?

+0

的[PartialFunction的瘦臉方法的逆]可能重複(http://stackoverflow.com/questions/5902266/inverse-of-partialfunctions-lift-method) – 2014-12-28 07:18:56

+0

@ToddOwen我只是好奇什麼是「前」是指你在句子「這個問題之前已經被問過」。請簡單比較兩個問題的日期。 – 2014-12-29 18:29:16

+0

收起投票。對不起,這不是「之前」的問題,而是另一個問題似乎收到了更好的答案(28票)。但是現在我注意到,Thayne在這裏給出了相同的答案。 – 2014-12-30 14:32:10

回答

27

我知道這是一個古老的線程,但如果其他人遇到這個,Function.unlift目的正是這個。

12

如何:

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

哦!顯然我需要以某種方式重置我的大腦:)非常感謝! – 2009-12-15 16:28:53

+1

這應該作爲'Predef'中的隱式轉換提供。 – HRJ 2013-03-09 18:28:10

5

我想你可以重寫應用和isDefinedAt手,但我會做到這一點你會發現醜陋的方式。

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 
} 

測試:

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

然後,我認爲我更喜歡重寫'apply'和'isDefinedAt'。 – 2009-12-15 16:53:43

+0

謝謝! 儘管現在我在印象之下,需要編寫這個「轉換」代碼來告訴我一些問題,所以我想更徹底地思考。在任何實現中,我看到'f(x)'最少的問題將被調用兩次(在'Some'的情況下)。 – 2009-12-15 18:50:12

+0

是的,它會被調用兩次。你可以緩存結果,但這會很尷尬,而不是在部分函數中發生的事情。 – 2009-12-16 11:25:19