2009-12-15 20 views
19

Miễn là chúng ta có PartialFunction[X,R], thật dễ dàng chuyển đổi nó thành hàm trả về Option[R], ví dụ:Cách chuyển đổi X => Option [R] thành PartialFunction [X, R]

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

Tuy nhiên, những gì nếu nhiệm vụ là ngược lại: giả sử tôi có một hàm f nhận X như một cuộc tranh cãi và trở Option[R] như một kết quả. Và tôi muốn thực hiện PartialFunction[X,R] trong số đó. cách tốt nhất là gì?

Những gì tôi đã đi lên với vẻ bề ngoài khá xấu xí để hương vị của tôi:

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ó một số cách tốt hơn tôi đã bỏ lỡ?

+0

có thể trùng lặp của [Inverse của phương thức nâng của PartialFunction] (http://stackoverflow.com/questions/5902266/inverse-of-partialfunctions-lift-method) –

+0

@ToddOwen Tôi chỉ tò mò "trước" có nghĩa là gì bạn trong câu "câu hỏi này đã được hỏi trước". Vui lòng chỉ cần so sánh ngày của cả hai câu hỏi. –

+0

Đóng phiếu bầu đã rút lại. Xin lỗi, nó không phải là vấn đề "trước", mà đúng hơn là câu hỏi khác dường như đã nhận được một câu trả lời tốt hơn (với 28 phiếu). Nhưng bây giờ tôi nhận thấy rằng Thayne đã trả lời như vậy ở đây. –

Trả lời

27

Tôi biết đây là một chủ đề cũ, nhưng nếu bất cứ ai khác đi qua này, Function.unlift không chính xác này.

12

Làm thế nào về điều này:

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 !! Rõ ràng tôi cần phải thiết lập lại bộ não của tôi bằng cách nào đó :) Rất cám ơn! –

+1

Điều này sẽ được cung cấp dưới dạng chuyển đổi ngầm trong 'Predef' – HRJ

5

Tôi cho rằng bạn có thể ghi đè lên áp dụng và isDefinedAt bằng tay, nhưng tôi muốn làm điều đó theo cách bạn tìm thấy xấu xí.

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 
} 

Thử nghiệm:

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

Sau đó, một lần nữa, tôi nghĩ rằng tôi thích ghi đè' apply' và 'isDefinedAt' sau khi tất cả. –

+0

Cảm ơn bạn! Mặc dù bây giờ tôi đang bị ấn tượng rằng cần phải viết mã "chuyển đổi" này báo hiệu cho tôi về một số vấn đề, vì vậy tôi đang cố gắng suy nghĩ kỹ lưỡng hơn. Vấn đề nhỏ nhất tôi thấy 'f (x)' sẽ được gọi hai lần (trong trường hợp của 'Some') trong bất kỳ việc thực hiện nào. –

+0

Có, nó được gọi hai lần. Bạn có thể lưu vào bộ nhớ cache kết quả, nhưng điều đó sẽ khó xử, và không thực sự xảy ra ở một phần chức năng. –

Các vấn đề liên quan