本节主要内容
(一)函数字面量(值函数)
(二)匿名函数
(三)函数的简化
(四)函数参数
(四)闭包
函数字面量(值函数)
函数字面量(function literal),也称值函数(function values),指的是函数可以赋值给变量。
一般函数具有如下形式:
/*
函数字面量 function literal
=>左侧的表示输入,右侧表示转换操作
*/
scala> val increase=(x:Int)=>x+1
increase: Int => Int = <function1>
scala> println(increase(10))
11
//前面的语句等同于
scala> def increaseAnother(x:Int)=x+1
increaseAnother: (x: Int)Int
scala> println(increaseAnother(10))
11
//多个语句则使用{}
val increase2=(x:Int)=>{
println("Xue")
println("Tu")
println("Wu")
println("You")
x+1
}
scala>println(increase2(10))
Xue
Tu
Wu
You
11
//数组的map方法中调用(写法1)
scala> println(Array(1,2,3,4).map(increase).mkString(","))
2,3,4,5
函数的赋值给变量
scala> def fun1(name : String){println(name)} //fun1为函数的名称,(name:String)参数 Unit是返回值为Unit fun1: (name: String)Unit //现在将函数赋值给变量 //val fun1_v = fun1 _ //函数名 _ 中间一定要加空格 //这时候的fun1_v就是函数了 scala> val fun1_v = fun1 _ //fun1 _ 此时就表示函数本身了 //此时我们看出fun1_v就是函数了,参数的类型是String类型,返回值是Unit // => 是将左边的参数进行右边的加工。 fun1_v: String => Unit = <function1> scala> fun1("Spark") Spark
scala> fun1_v("Spark") Spark
scala> fun1_v("Scala") Scala
匿名函数 在实际工作的时候,比如算法设计我们可能不需要函数名称,只需要函数执行的功能就可以了,这时候我们就会使用匿名函数。 但是我们要使用它,就可以借助函数赋值给变量,变量就变成了函数的性质,将匿名函数赋值给变量。 匿名函数的定义规则: (参数 :类型) => 函数的操作 scala> val fun2 = (content : String) => println(content) fun2: String => Unit = <function1>
scala> fun2("Hadoop")
|
高阶函数
函数的参数也是函数,为啥可以?因为前面谈到了函数可以赋值给变量,而我们现在直接把函数作为函数的参数,也应该是可以的。这样的设计非常强大:
例如:我们使用函数去操作集合,可能需要循环遍历集合,这个时候我们就可以使用函数参数,而此时的函数参数具有遍历集合的功能。
//第一个参数,定义了一个函数,func是函数的名称,(String)是变量的类型,=>Unit指定函数的返回值是Unit //第一个传入参数的要求是: 定义一个函数,函数值是Unit scala> val hiScala = (content : String) => println(content) hiScala: String => Unit = <function1>
scala> def bigData(func : (String) => Unit,content:String){func(content)} bigData: (func: String => Unit, content: String)Unit
//传入的第一个参数是一个函数,传入第二个参数的时候,content就会作为参数传入//第一个hiScala函数里面 scala> bigData(hiScala,"Spark") Spark
//item => (2*item) 是一个匿名函数,作为参数传入到map()函数中,map函数的作用是循环遍历集合中的所有元素。 scala> array.map(item => (2*item)) res5: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16, 18) |
另外,高阶函数的返回值也有可能是函数
scala> def func_Returned(content : String) = (message : String) => println(message) // 匿名函数本身是返回值,所有返回类型是Unit,func_returned()函数的返回值类型// 是String. func_Returned: (content: String)String => Unit
scala> func_Returned("Spark") //执行结果是一个函数 //输入类型是字符串String,为啥呢?因为 (message : String) 输入参数是String,返回类//型是Unit,因为println(message)是一条打印语句。 res7: String => Unit = <function1>
scala> def func_Returned(content : String) = (message : String) => println(content + " " + message) func_Returned: (content: String)String => Unit
scala> val returned = func_Returned("Spark") returned: String => Unit = <function1>
//为啥会打印 Spark 此时的Spark是上面def func_Returned(content : String) = //(message : String) => println(content + " " + message)为参数的输入值 //为啥会打印Scala 因为returned = func_Returned("Spark"),是把函数的返回值为函数//的返回值赋值给了returned,也就相当于把(message : String) => println(content + " " + //message) 赋值给了returned,此时我们传入参数,也就是message的参数,content//之前传过了。
scala> returned("Scala") Spark Scala |
高阶函数的两个层面:
1. 函数的参数是函数
2. 函数的返回值是函数
高阶函数有一个重要的性质就是类型推断,可以自动推断出具体的参数和类型,并且对于只有一个参数的函数,可以声明掉小括号,如果在函数的函数体中,只使用一次输入参数的参数值的话,那么可以将函数的输入参数的名称省略,用下划线来代替。
1
|
f(x)
=
x + i
|
1
2
3
|
scala>
def
f(x
:
Int)
=
x + i
<console>
:
10
:
error
:
not found
:
value i
def
f(x
:
Int)
=
x + i
|
1
2
3
4
|
scala>
var
i
:
Int
<console>
:
10
:
error
:
only classes can have declared but undefined members
(Note that variables need to be initialized to be defined)
var
i
:
Int
|
1
|
def
f(x
:
Int)
=
(i
:
Int)
=
> (x+i)
|
1
2
3
4
5
6
7
8
9
10
11
|
object
ClosureOps {
def
main(args
:
Array[String])
:
Unit
=
{
def
f(x
:
Int)
=
(i
:
Int)
=
> (x+i)
val
a
=
f(
1
)
val
b
=
f(
2
)
println(a(
10
))
println(b(
20
))
}
}
|