Scala及函数式编程
一、函数式编程的特点
- 函数式编程中,函数作为一等公民,就是说函数的行为和普通变量没有区别,可以作为函参进行传递,也可以在函数内部声明一个函数,那么外城的函数就被称为高阶函数。
- 函数式编程需要定义“变量”都为常量,,但是并不要求必须是常量,这样的特性提高了编程的复杂度,但是可以大大简化并发编程
- Java中常用的并发模式是共享内存模型,依赖于线程与锁,代码编写不当可能出现死锁和竞争条件,随着线程的增加可能暂用大量的系统资源。Scala这样的函数式编程都是常量,不需要考虑并发性
- 一次赋值提高了编程的复杂性,一般通过循环来处理的变量就需要通过递归实现
二、Scala语法
Scala是可伸缩语言(Scalable language),类似于Java语言,一开始设计的初衷,是为了继承面向对象编程和函数式编程
三、Scala函数
Scala中哈数可以向变量一样作为函参使用,也可以将函数赋值给一个变量;
函数的床架你不依赖于类或者是对象,Java中函数的创建要依赖于类、抽象类或者接口
(1)Scala函数的定义
规范化写法:
def addInt(x:Int ,y:Int):Int = {
val total:Int = a+ b
return total
}
简化之后:
def addInt(x:Int,y:Int)= x + y
也可以直接将函数赋值给变量
val addInt = (x:Int , y:Int) => x + y
(2)Scala匿名函数
使用=>可以使用右边的算法,将左边的输入数据转换为新的输出数据,并且可以赋值给变量
val testVal = (s:Int) => s + 1
(3)Scala高阶函数
Scala使用术语高阶函数来表示那些把函数作为参数或者作为返回值作为返回结果的方法和函数。比如常见的map,filter、reduce等
(4)Scala的闭包
Scala中的闭包指的是当函数的变量超出它的有效作用域的时候,还能对函数内部的变量进行访问;Scala中的闭包捕获到的是变量的本身而不仅仅是变量的数值,当自由变量发生变化时,Scala中的闭包能够捕获到这个变化;如果自由变量在闭包内部发生变化,也会反映到函数外面定义的自由变量的数值。
(5)Scala部分应用函数
部分应用函数只是在“已有函数”的基础上,提供部分默认参数,未提供默认参数的地方使用下划线替代,从而创建出一个“函数值”,在使用这个函数值(部分应用函数)的时候,只需提供下划线部分对应的参数即可;部分应用函数本质上是一种值类型的表达式,在使用的时候不需要提供所有的参数,只需要提供部分参数。
(6)Scala科里化函数
Scala中的柯里化指的是将原来接受两个参数的函数变成一个新的接受一个参数的函数的过程,新的函数返回一个以原有第二个参数作为参数的函数。
具体操作:把一个参数列表的多个参数,变成多个参数列表
(7)柯里化的目的是什么?
要了解它的好处,我们需要一个实际中的例子。
例如,我们有一个用于格式化和输出信息的日志(logging)函数 log(date, importance, message)。在实际项目中,此类函数具有很多有用的功能,例如通过网络发送日志(log),在这儿我们仅使用 alert:
function log(date, importance, message) { alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`); }
让我们将它柯里化!
log = _.curry(log);
柯里化之后,log 仍正常运行:
log(new Date(), "DEBUG", "some debug"); // log(a, b, c)
……但是也可以以柯里化形式运行:
log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)
现在,我们可以轻松地为当前日志创建便捷函数:
// logNow 会是带有固定第一个参数的日志的偏函数
let logNow = log(new Date());
// 使用它 logNow("INFO", "message");
// [HH:mm] INFO message
现在,logNow 是具有固定第一个参数的 log,换句话说,就是更简短的“偏应用函数(partially applied function)”或“偏函数(partial)”。
我们可以更进一步,为当前的调试日志(debug log)提供便捷函数:
let debugNow = logNow("DEBUG"); debugNow("message"); // [HH:mm] DEBUG message