Scala(3) 函数式编程
2023-08-09 14:53:19
# Big Data
# Scala
5. 函数式编程
面向对象编程:
解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题
Scala是一个完全面向对象编程语言。万物皆对象
对象的本质:对数据和行为的一个封装
函数式编程
解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题
Scala是一个完全函数式编程语言。万物皆函数
函数的本质:函数可以当作一个值进行传递
Scala中函数式编程和面向对象编程完美融合在一起
5.1 函数基础
5.1.1 函数基本语法
基本语法
案例实操
1 |
|
5.1.2 函数和方法的区别
核心概念
- 为完成某一功能的程序语句的集合,称为函数
- 类中的函数称为方法
案例实操
- Scala可以在任何的语法结构中声明任何的语法
- 函数没有重载和重写的概念,方法可以进行重载和重写
- Scala中函数可以嵌套定义
1 |
|
5.1.3 函数定义
基础语法
1 |
|
5.1.4 函数参数
案例实操
1 |
|
5.1.5 函数至简原则
原则:能省就省
内容
- return可以省略,Scala会使用函数体的最后一行代码作为返回值
- 如果函数体只有一行代码,可以省略花括号
- 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
- 如果有return,则不能省略返回值类型,必须指定
- 如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
- Scala如果期望是无返回值类型,可以省略等号
- 如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
- 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
- 如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
案例实操
1 |
|
5.2 函数高级
5.2.1 高阶函数
对于一个函数,我们可以:定义函数、调用函数
但函数还有更高级的用法
函数可以作为值进行传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def main(args: Array[String]): Unit = {
// 1.调用foo函数,把返回值给变量f
val f = foo()
println(f)
// 2.在被调用函数foo后面加上 _ ,相当于把函数foo作为一个整体,传递给变量f1
val f1 = foo _
foo
f1() // 不能省略()
// 3.如果明确变量类型, 那么不使用下划线也可以将函数作为整体传递给变量
var f2: () => Int = foo
f2()
}
def foo(): Int = {
println("foo...")
1
}
函数可以作为参数进行传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def main(args: Array[String]): Unit = {
// 1.定义一个函数,函数参数还是一个函数签名
// f表示函数名称, (Int, Int)表示输入两个Int参数, Int表示函数返回值
def f1(f: (Int, Int) => Int): Int = {
f(2, 4)
}
// 2.定义一个函数,参数和返回值类型和f1的输入参数一致
def add(a: Int, b: Int): Int = a + b
// 3.将add函数作为参数传递给f1, 如果能够推断出来不是调用, _ 可以省略
println(f1(add))
println(f1(add _))
// 可以传递匿名函数
}函数可以作为函数返回值返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14def main(args: Array[String]): Unit = {
def f1() = {
def f2() = {
println("f2")
}
f2 _
}
val f = f1()
// 因为f1函数的返回值依然为函数,所以变量f可以作为函数继续调用
f()
// 上面代码可以简化为
f1()()
}
5.2.2 匿名函数
说明
没有名字的函数就是匿名函数
(x: Int) => {函数体}
传递匿名函数至简原则
- 参数的类型可以省略,会根据形参自动推导
- 类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况: 没有参数和参数超过1的永远不能省略圆括号
- 匿名函数如果只有一行,则大括号也可以省略
- 如果参数只出现一次,则参数省略且后面参数可以用_代替
案例实操
单个参数版
1 |
|
多个参数版
1 |
|
5.2.3 高阶函数案例
模拟Map映射、Filter过滤、Reduce聚合
1 |
|
5.2.4 函数柯里化 & 闭包
说明
闭包
: 如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
函数柯里化
: 把一个参数列表的多个参数,变成多个参数列表
案例实操
1 |
|
5.2.5 递归
Scala中的递归必须声明函数返回值类型
1 |
|
5.2.6 控制抽象
值调用:把计算后的值传递进去
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def main(args: Array[String]): Unit = {
def f = () => {
println("f...")
10
}
foo(f())
}
def foo(a: Int): Unit = {
println(a)
println(a)
}
// 输出结果
// f...
// 10
// 10名调用:把代码块传递过去
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36def main(args: Array[String]): Unit = {
def f = () => {
println("f...")
10
}
foo(f())
foo({
println("这是一个代码块")
19
})
// 小括号可以省略
foo{
println("这是一个代码块")
29
}
}
// def foo(a: Int): Unit = {
// => Int: 传递代码块, 且返回值为Int
def foo(a: => Int): Unit = {
println(a)
println(a)
}
// 输出结果
// f...
// 10
// f...
// 10
// 这是一个代码块
// 19
// 这是一个代码块
// 19
// 这是一个代码块
// 29
// 这是一个代码块
// 29
案例实操
自定义while循环
1 |
|
5.2.7 惰性加载
说明
当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数
案例实操
1 |
|
注意:lazy不能修饰var类型的变量