2014-09-29 31 views
1

作爲一個例子,我們定義一個函數,它應該分別轉換爲「foo」,「bar」,「qix」和所有其他整數爲「X」 。如何知道何時使用PartialFunction與返回選項

我想出了2個實現: 方法f需要分開,因爲它可以在其他上下文中重用。

def f(i: Int): Option[String] = i match { 
    case 1 => Some("foo") 
    case 3 => Some("bar") 
    case 42 => Some("qix") 
    case _ => None 
} 

def g(i: Int) : String = f(i).getOrElse("X") 

和:

def f_ : PartialFunction[Int, String] = { 
    case 1 => "foo" 
    case 3 => "bar" 
    case 42 => "qix" 
} 

def g_(i: Int) : String = f_.orElse { case _ => "X" }(i) 

我傾向於選擇第二個,因爲它避免許多重複的部分(...)

WDYT?

+1

沒有人說你必須在比賽中使用'Some' – 2014-09-29 07:58:03

+2

請注意,你可以提升部分功能。在你的情況'f_.lift == f' – knutwalker 2014-09-29 08:02:18

回答

1

根據您的評論編輯我的例子:

def f(i: Int): Option[String] = { 
    val map = Map(1 -> "foo", 3 -> "bar", 42 -> "qix") 
    i match { 
    case x if (map.contains(x)) => Some(map(x)) 
    case _ => None 
    } 
} 

def g(i: Int) : String = f(i).getOrElse("X") 

我認爲函數應爲整數反應在一些有意義的方式給定的範圍之外。這就是爲什麼我更喜歡Option

+0

我編輯了我的問題來解釋2個函數的需要。 – 2014-09-29 08:19:55

+0

@YannMoisan我相應地編輯了我的答案 – 2014-09-29 08:27:11

+0

我已經編輯了我的問題,但並不一定是我的真實案例中的一個範圍。 – 2014-09-29 08:38:38

3

我不知道爲什麼要使用選項在所有的時候可以很容易地做到這一點,並得到完全相同的結果:

def f(i: Int): String = i match { 
    case 1 => "foo" 
    case 3 => "bar" 
    case 42 => "qix" 
    case _ => "X" 
} 

它甚至可以節省你討厭getOrElse

你甚至可以去一個更好的使用既不是PartialFunctionmatch,只是這樣做:

def f: Int => String = { 
    case 1 => "foo" 
    case 3 => "bar" 
    case 42 => "qix" 
    case _ => "X" 
} 

從而節省你寫一個disposab le i

+0

我編輯了我的問題來解釋2個功能的需要。 – 2014-09-29 08:37:46

0

選項是處理空值的好方法。 部分功能僅僅是一個部分匹配,他們不一樣的,即使選項和PartialFunction都有類似否則容易方法

由於部分功能是功能,因此它可以被鏈接,但是選項不能,Option是處理空值的方式。

因爲你可以像這樣的部分功能,它更像責任

def f_1 : PartialFunction[Int, String] = { 
    case 1 => "1" 
} 

def f_2 : PartialFunction[Int, String] = { 
    case 2 => "2" 
} 

def f_3 : PartialFunction[Int, String] = { 
    case 3 => "3" 
} 

f_1.orElse(f_2).orElse(f_3)(3) 
0

你可能想試試這個鏈。這裏的HashMap讓你快速查找:

object SomeMain { 
    import scala.collection.immutable.HashMap 
    def f(i: Int): Option[String] = { 
    HashMap(1 -> "foo", 3 -> "bar", 42 -> "qix").get(i).orElse(None) 
    } 

    def g(i: Int): String = f(i).getOrElse("X") 

    def main(args: Array[String]) { 
    List(1, 3, 42, 10) foreach { x => println(x + ": " + g(x)) } 
    } 
} 

輸出:

1: foo 
3: bar 
42: qix 
10: X 
3

fScala的地圖已經是一個局部的功能。因此,您可以使用它來代替定義您自己的函數,該函數完全執行Map所做的操作 - 「從A類鍵到B類值的映射」。
因此,所有你需要做的就是:

val f = Map(1 -> "foo", 3 -> "bar", 42 -> "qix") 
def g(i: Int) = f.getOrElse(i, "X") 

f(1) //foo 
f(4) // throw NoSuchElementException: Key not found: 4 
f.get(1) // Some(foo) 
f.get(4) // None 
g(1) //foo 
g(4) //X 

現在你可以使用函數「G」或再使用「F」其他需要。

相關問題