函数式编程
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
网友评论