4. 操作也是對象(Operations Are Objects)
Scala是一種函數式編程語言,也就是說每一個函數都是一個值。Scala有很簡潔的語法用於定義匿名和curry化函數(curried function,functional programming的概念之一,名字源於Haskell Curry,Haskell的發明者,一般都不翻譯。本文後面並沒有針對這個概念的解釋和實現,有興趣者請參閱相關參考資料——譯註),以及嵌套函數等。
4.1. 方法是函數式值(Methods are Functional Values)
爲了演示如何將函數作爲一個值使用,我們定義一個exists函數,用於檢測一個數組當中是否有符合條件的元素:
def exists[T](xs: Array[T], p: T => Boolean) = {
var i: Int = 0
while (i < xs.length && !p(xs(i))) i = i + 1
i < xs.length
}
方法參數[T]表示數組類型是任意的(類型參數在5.1節中詳細介紹),參數p表示驗證條件也是任意的,p的類型是函數類型(function type)T=>Boolean,表示所有定義域是T類型,值域是Boolean的函數。函數參數可以像普通函數一樣執行,如上面的循環體中顯示的p被調用那樣。以函數作爲參數或者返回值的函數,稱爲高階函數。
定義了exists,我們可以通過雙重否定來定義一個函數forall,表示數組的所有元素沒有一個不符合條件的,該函數定義如下:
def forall[T](xs: Array[T], p: T => boolean) = {
def not_p(x: T) = !p(x)
!exists(xs, not_p)
}
函數forall內部定義了一個嵌套函數not_p,表示不滿足條件p。嵌套函數可以訪問所在環境的函數參數和本地變量,例如not_p訪問了forall的參數p。
Scala還可以定義一個沒有名字的函數,例如下面這個簡版的forall函數:
def forall_short[T](xs: Array[T], p: T => boolean) =
!exists(xs, (x: T) => !p(x))
其中(x: T) => !p(x)定義了一個匿名函數(anonymous function),將類型爲T的參數p映射爲!p(x)。
有了exists和forall,我們可以定義一個函數hasZeroRow,用以檢驗一個二維矩陣是否有一行全是0:
def hasZeroRow(matrix: Array[Array[int]]) =
exists(matrix, (row: Array[int]) => forall(row, 0 ==))
表達式forall(row, 0 ==)用於檢測row是否只包含0。這裏,0的==方法被作爲參數傳遞給forall的參數p,這顯示了方法本身也是值,有點類似於C#中的“delegates”。