1. 偏函數(shù)
偏函數(shù)(Partial Function)形娇,是一個(gè)數(shù)學(xué)概念它不是"函數(shù)"的一種, 它跟函數(shù)是平行的概念瞭空。
Scala中的Partia Function是一個(gè)Trait讳推,其的類型為PartialFunction[A,B],其中接收一個(gè)類型為A的參數(shù)昔字,返回一個(gè)類型為B的結(jié)果。
舉個(gè)例子
scala> val pf:PartialFunction[Int,String] = {
| case 1=>"One"
| case 2=>"Two"
| case 3=>"Three"
| case _=>"Other"
| }
pf: PartialFunction[Int,String] = <function1>
scala> pf(1)
res0: String = One
scala> pf(2)
res1: String = Two
scala> pf(3)
res2: String = Three
scala> pf(4)
res3: String = Other
偏函數(shù)內(nèi)部有一些方法首繁,比如isDefinedAt李滴、OrElse、 andThen蛮瞄、applyOrElse等等所坯。
1.1 isDefinedAt
isDefinedAt : 這個(gè)函數(shù)的作用是判斷傳入來(lái)的參數(shù)是否在這個(gè)偏函數(shù)所處理的范圍內(nèi)。
剛才定義的pf來(lái)嘗試使用isDefinedAt()挂捅,只要是數(shù)字都是正確的芹助,因?yàn)橛衏ase _=>"Other"這一句。如果換成其他類型就會(huì)報(bào)錯(cuò)闲先。
scala> pf.isDefinedAt(1)
res4: Boolean = true
scala> pf.isDefinedAt(2)
res5: Boolean = true
scala> pf.isDefinedAt("1")
<console>:13: error: type mismatch;
found : String("1")
required: Int
pf.isDefinedAt("1")
^
scala> pf.isDefinedAt(100)
res7: Boolean = true
那我們?cè)俣x一個(gè)PartialFunction
scala> val anotherPF:PartialFunction[Int,String] = {
| case 1=>"One"
| case 2=>"Two"
| case 3=>"Three"
| }
anotherPF: PartialFunction[Int,String] = <function1>
scala> anotherPF.isDefinedAt(1)
res8: Boolean = true
scala> anotherPF.isDefinedAt(2)
res9: Boolean = true
scala> anotherPF.isDefinedAt(3)
res10: Boolean = true
scala> anotherPF.isDefinedAt(4)
res11: Boolean = false
去掉了原先的最后一句状土,再執(zhí)行anotherPF.isDefinedAt(4)會(huì)返回false。
1.2 orElse
orElse : 將多個(gè)偏函數(shù)組合起來(lái)使用伺糠,效果類似case語(yǔ)句蒙谓。
scala> val onePF:PartialFunction[Int,String] = {
| case 1=>"One"
| }
onePF: PartialFunction[Int,String] = <function1>
scala> val twoPF:PartialFunction[Int,String] = {
| case 2=>"Two"
| }
twoPF: PartialFunction[Int,String] = <function1>
scala> val threePF:PartialFunction[Int,String] = {
| case 3=>"Three"
| }
threePF: PartialFunction[Int,String] = <function1>
scala> val otherPF:PartialFunction[Int,String] = {
| case _=>"Other"
| }
otherPF: PartialFunction[Int,String] = <function1>
scala> val newPF = onePF orElse twoPF orElse threePF orElse otherPF
newPF: PartialFunction[Int,String] = <function1>
scala> newPF(1)
res0: String = One
scala> newPF(2)
res1: String = Two
scala> newPF(3)
res2: String = Three
scala> newPF(4)
res3: String = Other
這樣,newPF跟原先的pf效果是一樣的训桶。
1.3 andThen
andThen: 相當(dāng)于方法的連續(xù)調(diào)用累驮,比如g(f(x))酣倾。
scala> val pf1:PartialFunction[Int,String] = {
| case i if i == 1 => "One"
| }
pf1: PartialFunction[Int,String] = <function1>
scala> val pf2:PartialFunction[String,String] = {
| case str if str eq "One" => "The num is 1"
| }
pf2: PartialFunction[String,String] = <function1>
scala> val num = pf1 andThen pf2
num: PartialFunction[Int,String] = <function1>
scala> num(1)
res4: String = The num is 1
pf1的結(jié)果返回類型必須和pf2的參數(shù)傳入類型必須一致,否則會(huì)報(bào)錯(cuò)谤专。
1.4 applyOrElse
applyOrElse:它接收2個(gè)參數(shù)躁锡,第一個(gè)是調(diào)用的參數(shù),第二個(gè)是個(gè)回調(diào)函數(shù)置侍。如果第一個(gè)調(diào)用的參數(shù)匹配映之,返回匹配的值,否則調(diào)用回調(diào)函數(shù)蜡坊。
scala> onePF.applyOrElse(1,{num:Int=>"two"})
res5: String = One
scala> onePF.applyOrElse(2,{num:Int=>"two"})
res6: String = two
在這個(gè)例子中杠输,第一次onePF匹配了1成功則返回的是"One"字符串。第二次onePF匹配2失敗則觸發(fā)回調(diào)函數(shù)秕衙,返回的是"Two"字符串蠢甲。
2. 偏應(yīng)用函數(shù)
偏應(yīng)用函數(shù)(Partial Applied Function)也叫部分應(yīng)用函數(shù),跟偏函數(shù)(Partial Function)從英文名來(lái)看只有一字之差灾梦,但他們二者之間卻有天壤之別峡钓。
部分應(yīng)用函數(shù), 是指一個(gè)函數(shù)有n個(gè)參數(shù), 而我們?yōu)槠涮峁┥儆趎個(gè)參數(shù), 那就得到了一個(gè)部分應(yīng)用函數(shù)妓笙。
個(gè)人理解的偏應(yīng)用函數(shù)類似于柯里化若河,可以參考我以前寫(xiě)的文章借助Java 8實(shí)現(xiàn)柯里化
舉個(gè)例子,定義好一個(gè)函數(shù)有3個(gè)參數(shù)寞宫,再提供幾個(gè)有1-2個(gè)已知參數(shù)的偏應(yīng)用函數(shù)
scala> def add(x:Int,y:Int,z:Int) = x+y+z
add: (x: Int, y: Int, z: Int)Int
scala> def addX = add(1,_:Int,_:Int) // x 已知
addX: (Int, Int) => Int
scala> addX(2,3)
res1: Int = 6
scala> addX(3,4)
res2: Int = 8
scala> def addXAndY = add(10,100,_:Int) // x 和 y 已知
addXAndY: Int => Int
scala> addXAndY(1)
res3: Int = 111
scala> def addZ = add(_:Int,_:Int,10) // z 已知
addZ: (Int, Int) => Int
scala> addZ(1,2)
res4: Int = 13
總結(jié)
本篇筆記是為了下一篇 Scala 模式匹配所做的鋪墊萧福。模式匹配會(huì)用到偏函數(shù),所以先整理出來(lái)辈赋。還詳細(xì)介紹了偏函數(shù)和偏應(yīng)用函數(shù)的區(qū)別鲫忍。
先前的文章:
Scala學(xué)習(xí)筆記(五) 抽象類以及類中的一些語(yǔ)法糖
Scala學(xué)習(xí)筆記(四) 類的初步
Scala學(xué)習(xí)筆記(三)
Scala學(xué)習(xí)筆記(二)
Scala學(xué)習(xí)筆記(一)