2.2 函数式编程的特点
函数式编程具有如下特点。
函数是一等公民:函数与其他数据类型一样,处于平等地位,不但可以将函数作为参数、返回值使用,而且可以用函数名进行引用,甚至可以匿名调用。下面的例子展示了函数作为参数、返回值、匿名函数的用法。
引用透明,无副作用:函数的运行不依赖外部变量或“状态”,只依赖输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。副作用是指有超出函数控制的操作,比如在执行过程中操作文件系统、数据库等外部资源。没有副作用使得函数式编程各个独立部分的执行顺序可以被随意打乱,多个线程之间不共享状态,不会造成资源争用,不需要用锁来保护可变状态,不会出现死锁,这样可以更好地进行无锁的并发操作。
在下面的例子中,xs是不可变对象,多次调用xs.slice方法,入参相同,返回结果相同。xs1是可变对象,多次调用xs1.add方法,会改变xs1的值,产生副作用。
高阶函数:可以将函数作为参数进行传递,也可以在函数内部声明一个函数,那么外层的函数就被称作高阶函数。
柯里化(Currying):把接收多个参数的函数变换成接收单一参数的函数,返回新函数,该函数接收余下的参数并且返回结果。柯里化的好处是减少了函数的参数个数,并且模块化了每一步计算,与设计模式中的适配器模式(将一个接口转换为另一个接口)类似。并且柯里化的应用之一—惰性求值,也是函数式编程的一个重要特性。惰性求值在将表达式赋值给变量(或称作绑定)时并不计算表达式的值,而是在变量第一次被使用时才进行计算。
下面的例子展示了柯里化、惰性求值。add(1)输入一个参数,返回一个函数;add(1)(2),输入两个参数,返回一个函数;add(1)(2)(3)输入三个参数,返回一个结果。惰性求值在调用时才进行初始化,println(y)方法不会初始化y,println(y.values)方法才会初始化y。