scala中的高阶函数和柯里化
2018-01-23 22:09
295 查看
高阶函数
在计算机科学中,高阶函数是至少满足下列一个条件的函数:接受至少一个函数作为输入
输出一个函数
在数学中它们也叫做算子(运算符)或泛函。微积分中的导数就是常见的例子,因为它映射一个函数到另一个函数。
高阶函数的例子
假设有一个函数对给定两个数区间中的所有整数求和:def sumInts(a: Int, b: Int): Int = if(a > b) 0 else a + sumInts(a + 1, b)
如果现在要求连续整数的平方和:
def square(x: Int): Int = x * x def sumSquares(a: Int, b: Int): Int = if(a > b) 0 else square(a) + sumSquares(a + 1, b)
如果要计算2的幂次的和:
def powerOfTwo(x: Int): Int = if(x == 0) 1 else 2 * powerOfTwo(x-1) def sumPowersOfTwo(a: Int, b: Int): Int = if(a > b) 0 else powerOfTwo(a) + sumPowersOfTwo(a+1, b)
上面的函数都是从a到b的f(n)的累加形式,我们可以抽取这些函数中共同的部分重新编写函数sum,其中定义的f作为一个参数传入到高阶函数sum中:
def sum(f: Int => Int, a: Int, b: Int): Int = if(a > b) 0 else f(a) + sum(f, a+1, b) def id(x: Int): Int = x def square(x: Int): Int = x * x def powerOfTwo(x: Int): Int = if(x == 0) 1 else 2 * powerOfTwo(x-1) def sumInts(a: Int, b: Int): Int = sum(id, a, b) def sumSquared(a: Int, b: Int): Int = sum(square, a, b) def sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b)
改写成尾递归的写法
object Demo { def sum(f: Int => Int, a: Int, b: Int) = { def loop(a: Int, acc: Int): Int = if(a > b) acc else loop(a + 1, f(a) + acc) loop(a, 0) } def main(args: Array[String]) = { println(sum(x => x * x, 3, 5)) } }
应用
map方法将一个函数应用到某个集合的所有元素并返回结果;foreach将函数应用到每个元素。
//打印三角形 scala> (1 to 9).map("^" * _).foreach(println _) /* ^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^ ^^^^^^^ ^^^^^^^^ ^^^^^^^^^ */
filter方法输出所有匹配某个特定条件的元素:
scala> (1 to 9).filter(_ % 2 == 0) res14: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8)
这些在Java、Python、Javascript和新版本的C++里都有实现。
大家如果在平时的编程之中可以适当地实用一点这样的技巧,使得代码更加简洁。
柯里化
最简单的柯里化指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。如下代码段,add(x, y)就是一般的函数,
addCurry(x)(y)就是柯里化函数。
推广来说,柯里化函数有多个参数列表,所谓的参数列表就是使用小括号括起来的函数参数列表。
def add(x: Int, y: Int) = x + y def addCurry(x: Int)(y: Int) = x + y
返回函数的函数
在上面高阶函数的例子中,我们通过def sumInts(a: Int, b: Int): Int = sum(x => x, a, b)来定义新的函数,上面这函数每次都要传a和b两个参数到sum函数中,我们可以通过返回函数的函数来简化参数:
def sum1(f: Int => Int): (Int, Int) => Int = { def sumF(a: Int, b: Int): Int = if(a > b) 0 else f(a) + sumF(a+1, b) sumF } def sumInts = sum1(x => x) def sumSquared = sum1(x => x * x) def sumPowersOfTwo = sum1(powerOfTwo)
多个参数列表
我们可以这样定义sum函数,进一步简化,省去sumInts、sumSquared、sumPowersOfTwo这几个中间函数的形式(当然,不省去也行):def sum2(f: Int => Int)(a: Int, b: Int): Int = if(a > b) 1 else f(a) + sum2(f)(a+1, b) def sumInts(a: Int, b:Int) = sum2(x => x)(a, b) def sumSquared(a: Int, b:Int) = sum2(x => x * x)(a, b) def sumPowersOfTwo(a: Int, b:Int) = sum2(powerOfTwo)(a, b)
这使得函数编写更加简洁。
一般的,多参数函数定义为
def f(args1)...(argsn) = E,
当
n > 1时,等同于
def f(args1)...(args n-1) = {def g(argsn) = E; g}或者
def f(args1)...(args n-1) = (argsn => E)。
如果重复这个过程n次,得到
def f = (args1 => (args2 => ... (argsn => E) ) )。
这种函数定义称为柯里化(Currying)。
参考资料
1.scala中的柯里化函数2.【Scala十六】Scala核心十:柯里化函数
相关文章推荐
- scala25-CurringCurring(柯里化)
- Scala 深入理解高阶函数
- Scala初体验:高阶函数
- scala基础26-高阶函数
- scala高阶函数总结
- scala学习笔记:高阶函数
- scala基础5⃣️高阶函数
- 第12节:Scala函数式编程进阶(匿名函数,高阶函数,函数类型推断,currying柯里化)
- Scala的高阶函数使用总结
- scala学习笔记:高阶函数
- Scala高阶函数
- Scala-高阶函数
- scala的高阶函数
- Scala之 闭包和柯里化
- Scala 学习笔记(六)------定义高阶函数
- scala高阶函数
- scala 高阶函数编程
- Scala高阶函数,闭包,颗粒化,集合
- scala基础28-柯里化
- 01-scala-高阶函数