2 回答

TA貢獻1818條經驗 獲得超3個贊
總結如下:
部分應用函數(Partial Applied Function)是缺少部分參數的函數,是一個邏輯上概念
偏函數是只對函數定義域的一個子集進行定義的函數。 scala中用scala.PartialFunction[-T, +S]類來表示
比如定義了一個函數:def sum(x: Int)(y: Int) = x + y, 當調用sum的時候,如果不提供所有的參數或某些參數還未知時,比如sum _ , sum(3)(_: Int), sum(_: Int)(3), 這樣就生成了所謂的部分應用函數。部分應用函數只是邏輯上的一個表達,scala編譯器會用Function1, Function2這些類來表示它.
下面這個變量signal引用了一個偏函數
val signal: PartialFunction[Int, Int] = {
case x if x > 1 => 1
case x if x < -1 => -1
}
這個signal所引用的函數除了0值外,對所有整數都定義了相應的操作。 signal(0) 會拋出異常,因此使用前最好先signal.isDefinedAt(0)判斷一下。 偏函數主要用于這樣一種場景:對某些值現在還無法給出具體的操作(即需求還不明朗),也有可能存在幾種處理方式(視乎具體的需求);我們可以先對需求明確的部分進行定義,比如上述除了0外的所有整數域,然后根據具體情況補充對其他域的定義,比如 :
val composed_signal: PartialFunction[Int,Int] = signal.orElse{
case 0 => 0
}
composed_signal(0) // 返回 0
或者對定義域進行一定的偏移(假如需求做了變更, 1 為無效的點)
val new_signal: Function1[Int, Int] = signal.compose{
case x => x - 1
}
new_signal(1) // throw exception
new_signal(0) // 返回 -1
new_signal(2) // 返回 1
還可以用andThen將兩個相關的偏函數串接起來
val another_signal: PartialFunction[Int, Int] = {
case 0 => 0
case x if x > 0 => x - 1
case x if x < 0 => x + 1
}
val then_signal = another_signal andThen signal
這里的then_signal 剔除了-1, 0, 1三個點的定義

TA貢獻1895條經驗 獲得超3個贊
部分應用函數:
你還可以使用單個“_”替換整個參數列表。例如可以寫成:
List(1,2,3,4,5).foreach(println(_))
或者更好的方法是你還可以寫成:
List(1,2,3,4,5).foreach(println _)
以這種方式使用下劃線時,你就正在寫一個部分應用函數。部分應用函數是一種表達式,你不需要提供函數需要的所有參數,代之以僅提供部分,或不提供所需參數。如下先定義一個函數,然后創(chuàng)建一個部分應用函數,并保存于變量,然后該變量就可以作為函數使用:
def sum(a: Int, b: Int, c: Int) = a + b + c
val a = sum _
println(a(1,2,3))
實際發(fā)生的事情是這樣的:名為a的變量指向一個函數值對象,這個函數值是由scala編譯器依照部分應用函數表達式sum _,自動產生的類的一個實例。編譯器產生的類有一個apply方法帶有3個參數(之所以帶3個參數是因為sum _表達式缺少的參數數量為3),然后scala編譯器把表達式a(1,2,3)翻譯成對函數值的apply方法的調用。你可以使用這種方式把成員函數和本地函數轉換為函數值,進而在函數中使用它們。不過,你還可以通過提供某些但不是全部需要的參數表達一個部分應用函數。如下,此變量在使用的時候,可以僅提供一個參數:
val b = sum(1, _: Int, 3)
如果你正在寫一個省略所有參數的部分應用函數表達式,如println _或sum _,而且在代碼的那個地方正需要一個函數,你就可以省略掉下劃線(不是需要函數的地方,你這樣寫,編譯器可能會把它當作一個函數調用,因為在scala中,調用無副作用的函數時,默認不加括號)。如下代碼就是:
List(1,2,3,4,5).foreach(println)
偏函數:
偏函數和部分應用函數是無關的。偏函數是只對函數定義域的一個子集進行定義的函數。scala中用scala.PartialFunction[-T,+S]來表示。偏函數主要用于這樣一種場景:對某些值現在還無法給出具體的操作(即需求還不明朗),也有可能存在幾種處理方式(視乎具體的需求),我們可以先對需求明確的部分進行定義,以后可以再對定義域進行修改。PartialFunction中可以使用的方法如下:
isDefinedAt:判斷定義域是否包含指定的輸入。
orElse:補充對其他域的定義。
compose:組合其他函數形成一個新的函數,假設有兩個函數f和g,那么表達式f _ compose g _則會形成一個f(g(x))形式的新函數。你可以使用該方法對定義域進行一定的偏移。
andThen:將兩個相關的偏函數串接起來,調用順序是先調用第一個函數,然后調用第二個,假設有兩個函數f和g,那么表達式f _ andThen g _則會形成一個g(f(x))形式的新函數,剛好與compose相反。
- 2 回答
- 0 關注
- 710 瀏覽
添加回答
舉報