詳解 groovy 的閉包(下)
函數語言程式設計
curry 化
最開始接觸這個概念時候我是在 javascript 函數語言程式設計這本書中接觸到的。首先給出一個概念,就是偏函式
在函數語言程式設計中最理想也是我們想要的是輸入一個引數給函式返回一個值,因此出現偏函式來將多個引數的函式化簡為單一引數的函式。大家這樣就理解了吧。
def nCopies = { int n, String str -> str*n } def twice = nCopies.curry(2) println twice("hey")
通過 rcurry 可以實現右curry化
def nCopies = { int n, String str -> str*n } def blah = nCopies.rcurry('bla')
memoization
如果我們使用相同引數來反覆地呼叫一個函式,為了避免重複計算我們可以使用 memoization 來根據引數.
組合
這些都是函式程式設計一些特點,可以解決函式先後執行的順序的問題。我們在面向物件中可能在要執行一個方法,需要等待另一個函式返回的值作為引數來使用。我們可以通過組合來講簡單函式按一定順序組合在一起來實現一些複雜的功能。
def plus2= { it + 2 } def times3 = { it * 3 } def times3plus2 = plus2 << times3 assert times3plus2(3) == 11 assert times3plus2(4) == plus2(times3(4)) def plus2times3 = times3 << plus2 assert plus2times3(3) == 15 assert plus2times3(5) == times3(plus2(5)) // reverse composition assert times3plus2(3) == (times3 >> plus2)(3)
- 定義兩個閉包 plus2 times3
- 這裡我們可以times3plus2(3) = 3 * 3 + 2 = 11, << 表示資料的流向 ,如果我們將 plus2 >> times3 = (2+ 3) * 3 =15
Trampoline
Trampoline 解決的問題多次回撥函式時,函式棧溢位的問題。如果遞迴函式回撥次數過多,超過函式棧的高度,就會發生棧溢位異常。
def factorial factorial = { int n, def accu = 1G -> if (n < 2) return accu factorial.trampoline(n - 1, n * accu) } factorial = factorial.trampoline() assert factorial(1)== 1 assert factorial(3)== 1 * 2 * 3 assert factorial(1000) // == 402387260.. plus another 2560 digits