Scala-Partial Functions(偏函數)

若是你想定義一個函數,而讓它只接受和處理其參數定義域範圍內的子集,對於這個參數範圍外的參數則拋出異常,這樣的函數就是偏函數(顧名思異就是這個函數只處理傳入來的部分參數)。java

偏函數是個特質其的類型爲PartialFunction[A,B],其中接收一個類型爲A的參數,返回一個類型爲B的結果。
其有個重要的函數就是:
def isDefinedAt(x: A): Boolean //做用是判斷傳入來的參數是否在這個偏函數所處理的範圍內

定義一個普通的除法函數:
scala> val divide = (x : Int) => 100/x
divide: Int => Int = <function1>
輸入參數0
scala> divide(0)
java.lang.ArithmeticException: / by zero 
顯然,當咱們將0做爲參數傳入時會報錯,通常的解決辦法就是使用try/catch來捕捉異常或者對參數進行判斷看其是否等於0;可是在Scala的偏函數中這些都已經封裝好了,以下:將divide定義成一個偏函數()
val divide = new PartialFunction[Int,Int] {
def isDefinedAt(x: Int): Boolean = x != 0 //判斷x是否等於0,當x = 0時拋出異常
def apply(x: Int): Int = 100/x
}  
可是,當偏函數與case語句結合起來就能使代碼更簡潔,以下:
val divide1 : PartialFunction[Int,Int] = {
case d : Int if d != 0 => 100/d //功能和上面的代碼同樣,這就是偏函數的強大之處,方便,簡潔!!
} 
其實這代碼就是對上面那段代碼的封裝,這裏一樣調用isDefinedAt方法
scala> divide1.isDefinedAt(0)
res1: Boolean = false
 
scala> divide1.isDefinedAt(10)
res2: Boolean = true 
再舉個與case結合使用的例子:
val rs : PartialFunction[Int , String] = {
case 1 => "One"
case 2 => "Two"
case _ => "Other"
}
輸入:
scala> rs(1)
res4: String = One
 
scala> rs(2)
res5: String = Two
 
scala> rs(100)
res6: String = Other
 
OrElse
OrElse方法能夠將多個偏函數組合起來使用,結合起來的效果相似case語句,可是每一個偏函數裏又能夠再使用case
scala> val or1 : PartialFunction[Int,String] = {case 1 => "One"}
or1: PartialFunction[Int,String] = <function1>
 
scala> val or2 : PartialFunction[Int,String] = {case 2 => "Two"}
or2: PartialFunction[Int,String] = <function1>
 
scala> val or_ : PartialFunction[Int,String] = {case _ => "Other"}
or_: PartialFunction[Int,String] = <function1>
 
scala> val or = or1 orElse or2 orElse or_ //使用orElse將多個偏結合起來
or: PartialFunction[Int,String] = <function1>
 
scala> or(1)
res7: String = One
 
scala> or(20)
res9: String = Other
orElse還能夠直接鏈接case使用
scala> val orCase:(Int => String) = or1 orElse {case _ => "Other"}
orCase: Int => String = <function1>
 
scala> orCase(1)
res10: String = One
 
scala> orCase(10)
res11: String = Other
   
 
andThen
對函數的結果進行下一步的處理
scala> val at1 : PartialFunction[Int,String] = {case cs if cs == 1 => "One"}
at1: PartialFunction[Int,String] = <function1>
 
scala> val at2 : PartialFunction[String,String] = {case cs if cs eq "One" => "The num is 1"}
at2: PartialFunction[String,String] = <function1>
 
scala> val num = at1 andThen at2
num: PartialFunction[Int,String] = <function1>
 
scala> num(1)
res18: String = The num is 1
 
注意:at1函數的結果返回類型必須和at2函數的參數傳入類型一致,否則會編譯報錯
相關文章
相關標籤/搜索