1 函数是第一等公民
Scala语言支持:
- 把函数作为实参传递给另外一个函数
- 把函数作为返回值
- 把函数赋值给变量
- 把函数存储在数据结构里
在Scala中,函数就像普通变量一样,同样也具有函数的类型。
函数类型格式:A => B
表示一个接受类型A的参数,并返回类型B的参数
eg: Int => String 是把整型映射为字符串的函数类型
2.高阶函数
用函数作为形参或返回值的函数,称为高阶函数
def operate(f:(Int,Int) => Int){
f(4,3)
}
def greeting() =(name:String) => {"hello" + "" + name}
3.匿名函数
匿名函数(Anonymous Function),也就是函数常量,也称为函数文字量(Function Literal)。
在Scala 中,匿名函数的定义格式为
(形参列表)=>{函数体}
eg:
object example {
def operate(x:Int)=x*x //> operate: (x: Int)Int
operate(2) //> res0: Int = 4
def add(x:Int,y:Int)=x+y //> add: (x: Int, y: Int)Int
add(1,2) //> res1: Int = 3
}
4.柯里化函数(Currried Function)
柯里化函数就是把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。
eg:以下两个add函数定义是等价的
def add(x : Int, y: Int) = x + y
def add(x: Int)(y: Int)= x + y //Scala里柯里化的语法
def curriedAdd(a: Int)(b: Int) = a + b
curriedAdd(2)(2) //a=2,b=2,a+b=4
val addOne - curriedAdd(1)_ //Int=>Int 通配符_,a=1,b是变量
addOne(2) //a=1,b=2,a+b=3
5.递归函数(Recursive Function)
递归函数在函数式编程是实现循环的以一种技术.
eg: 计算n!
def factorial(n:Int): Int =
if(n<=0) 1 //直接返回1
else n*factorial(n-1)
//缺点:堆栈进行函数调用的时候,递归层数越深就容易导致堆栈溢出
优化方案:尾递归函数(Tail Recursive Function)
所有递归形式的调用都出现在函数的末尾,当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是去栈中去创建一个新的。**
@annotation.tailrec
def factorial(n: Int,m:Int):Int =
if(n <=0) m
else factorial(n-1,m*n) //> factorial: (n: Int, m: Int)Int
factorial(5, 1) //> res2: Int = 120
}
综合性栗子: 求 ∑baf(x)
object Sumfunction{
def sum(f: Int => Int)(a: Int)(b: Int): Int= {
@annotation.tailrec
def loop(n: Int,acc: Int):Int = {
if(n > b){
println(s"n=${n},acc=${acc}")
acc
} else {
println(s"n=${n},acc=${acc}")
loop(n + 1,acc + f(n))
}
}
loop(a,0)
} // sum: (f: Int => Int)(a: Int)(b: Int)Int
--------------------------------------------------------
sum(x=>x*x)(1)(5) **** val sumSquare = sum(x=>x*x)_
sumSquare(1)(5)
-----------------------------------------------------------
sum(x=>x)(1)(5) // n=1,acc=0
// n=2,acc=1
//|n=3,acc=3
// n=4,acc=6
// n=5,acc=10
// n=6,acc=15
//res0: Int = 15
sum(x=>x*x)(1)(5) //> n=1,acc=0
//| n=2,acc=1
//| n=3,acc=5
//| n=4,acc=14
//| n=5,acc=30
//| n=6,acc=55
//| res1: Int = 55
sum(x=>x*x*x)(1)(5) //> n=1,acc=0
//| n=2,acc=1
//| n=3,acc=9
//| n=4,acc=36
//| n=5,acc=100
//| n=6,acc=225
//| res2: Int = 225
val sumSquare = sum(x =>x*x)_
sumSquare(1)(5)
//> n=1,acc=0
//| n=2,acc=1
//| n=3,acc=5
//| n=4,acc=14
//| n=5,acc=30
//| n=6,acc=55
//| res1: Int = 55
}