看akka源碼的時候看到這樣的一個用法:
作為接觸scala兩天半的我有些看不明白了。好一番搜索看到這樣的答案:
下面的問題,表面上看是小括號與花括號的問題。
// map方法這樣寫不能編譯通過
scala> List(2).map( case 2 => "OK" )
// 換做花括號就可以了
scala> List(2).map{ case 2 => "OK" }
不了解原因的話,覺得很詭異。分析一下,首先,map方法接受一個函數,這個函數將List中的元素映射為其他類型。
實際上case 2 => "OK"
不是一段lambda表達式(也就是說它不是函數),它是一段模式匹配語句。
那為什么在第二行可以編譯通過呢?
稍微有點基礎的話,會清楚方法的花括號有2種意思:
1)scala中函數的小括號,可以用花括號來表示,即foo{xx}
與 foo(xx)
是一回事兒。(這里一回事是指函數的小括號)
2)對於只有一個參數的方法,其小括號是可以省略的,map(lambda)
可寫為 map lambda
,即這塊{case 2 => "OK"}
連同花括號整體是一個lambda(函數字面量)。
這個就是最上面的問題的答案了。
這兒顯然是第2個(追究原因就要看編譯器在語法解析式的優先級了,看樣子把花括號對待為lambda字面量的一部分要高於把花括號當作小括號來對待),那么為什么加了花括號的{case 2 => "OK" }
就可以當作一段函數字面量?
這要引出偏函數的概念,所謂偏函數(也叫部分函數)與完全函數想對應,普通的方法都是完全函數,即 f(i:Int) = xxx
是將所有Int類型作為參數的,是對整個Int集的映射;而偏函數則是對部分數據的映射,比如上面{case 2=> "OK" }
就僅僅只對2做了映射。偏函數的實現都是通過模式匹配來表達的。
scala> val p:PartialFunction[Int,String] = { case 2 => "OK" }
因為偏函數是通過 { case x => y }
這種特殊的方式來描述的,上面的{case 2=>"OK"}
就被當作了一段偏函數字面量,而偏函數背后的類型PartialFunction[A,B]
是繼承自Function1[A,B]
的,所以將這段匿名的偏函數傳給map方法是ok的。
小結:表達式 {case x=>y}
會被當作偏函數字面量。