本文主要对 函数式编程语言 与 Scala 中的函数进行介绍
函数式编程语言
严格意义上来讲,一门函数式编程语言不需要有可变类型的变量,赋值操作,或者是循环等控制结构。
广义上来说,函数式编程语言可以关注于函数,写出优雅的代码。
在我们学习 Scala 的时候,相信大家都看过一句话,在函数式编程语言中,函数是一等公民。那么这句话是什么意思呢?
- 函数可以在任何地方被定义,甚至在其他函数内部
- 函数可以被当成函数的参数传递于函数的返回值返回
- 有一系列操作符可以把函数组合成其他函数
下面对 Scala 中的函数进行介绍
匿名函数
在 Scala 中不需要给每一个函数命名,就像是不需要给每一个数字命名一样。
和 Python 中的 lambda 表达式有些相似
// 匿名函数 把传入的参数乘3
(X : Int) => 3 * X
// 可以赋值给某个变量
val func = (x: Int) => 3*x
val a = Array(1,2,3)
// 以下三种写法等价 将a中的每个元素乘3
a.map(func)
a.map((x: Int) => 3*x)
// 不加句点的写法更加常见一些
a map(func)
# 对应的Python代码
list(map(lambda x:3*x, [1,2,3]))
函数做为函数的参数与返回值
// 函数做为参数
(f: (Double)=>Double) => f(3)
// 函数做为返回值
(x: Int) => ((n: Double)=>x*n)
参数(类型)推断
def func0(f: (Double) => Double) = f(3)
// 得到结果0.75
func0((x: Double) => 0.25 * x)
// 因为 func0 知道传入的函数类型,所以可以省略x的类型,简化为
func0((x) => 0.25 * x)
// 更进一步
func0(x => 0.25 * x)
// 再进一步 因为参数只在 => 右边出现了一次
func0(0.25 * _)
注意,以上所有的简写,都要在能够推断出类型的前提下
一些常用的高阶函数
val a = Array(1,2,3,4,5)
a.map(_ * 2)
a.filter(_ % 2==0)
a.reduceLeft(_ * _)
# 等价于Python中
a = [1,2,3,4,5]
list(map(lambda x: x*2, a))
list(filter(lambda x: x%2 == 0, a))
from functools import reduce
reduce(lambda x, y: x*y, a)
柯里化
指将原来接收两个参数的函数变成新的接受一个参数的函数的过程,新的函数返回一个以原有第二个参数作为参数的函数。
比如def mul(x: Int, y: Int)=x*y
转变成def newmul(x: Int)=(y: Int) => x*y
例如,对[a, b]区间内的数,求进行f运算后的乘积,
def sum(f: Int => Int, a: Int, b: Int) : Int ={
if (a>b) 1
else f(a)*sum(f, a+1, b)
}
可以柯里化成如下表示,
def sum(f: Int => Int): (Int, Int)=>Int ={
def tmp(a: Int, b: Int): Int ={
if (a>b) 1
else f(a)*tmp(a+1, b)
}
tmp
}
等价于
def sum(f: Int => Int)(a: Int, b: Int) : Int ={
if (a==b) 1
else f(a)*sum(f)(a+1, b)
}
参考资料:《Functional Programming Principles in Scala》