scala
函数式编程
1.基本语法
[修饰符] def 函数名 ( 参数列表 ) [:返回值类型] = {
函数体
}
private def test( s : String ) : Unit = {
println(s)
}
2.函数定义
无返回值,调用函数后不用print;有返回值,调用函数需要print
1)无参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun1(): Unit = {
println("函数体")
}
fun1()
}
}
2)无参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun2(): String = {
"zhangsan"
}
println( fun2() )
}
}
3)有参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun3( name:String ): Unit = {
println( name )
}
fun3("zhangsan")
}
}
4)有参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4(name:String): String = {
"Hello " + name
}
println( fun4("zhangsan") )
}
}
5)多参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(hello:String, name:String): Unit = {
println( hello + " " + name )
}
fun5("Hello", "zhangsan")
}
}
6)多参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun6(hello:String, name:String): String = {
hello + " " + name
}
println( fun6("Hello", "zhangsan"))
}
}
3.函数参数
3.1可变参数 (数据类型后面加*)
注意:可变参数不能放置在参数列表的前面,一般放置在参数列表的最后
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun7(names:String*): Unit = {
println(names)
}
fun7()
fun7( "zhangsan" )
fun7( "zhangsan", "lisi" )
}
}
3.2参数默认值
注意:参数默认值与可变参数不能同时使用
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun8( name:String, password:String = "000000" ): Unit = {
println( name + "," + password )
}
fun8("zhangsan", "123123")
fun8("zhangsan")
}
}
如果使name和password交换参数的位置,就没有办法使用默认参数值,故引入带名参数
3.2带名参数
参数传递一般是顺序传递,增加参数的名称,用于改变传参的顺序
object Function02 {
def main(args: Array[String]): Unit = {
def fun1(name: String ="lisi",password:String): Unit ={
println(name + password)
}
fun1(password = "123313")
}
}
4.函数至简原则
能省就省
4.1省略return关键字
函数体 会将满足条件的最后一行代码的执行结果作为函数的返回值
object Function02 {
def main(args: Array[String]): Unit = {
def fun1(): String={
"za"
}
println(fun1())
}
}
4.2省略花括号
如果函数体中的逻辑代码只有一行,那么花括号可以省略
object Function02 {
def main(args: Array[String]): Unit = {
def fun1(): String= "za"
println(fun1())
}
}
4.3省略返回值类型
如果函数返回数据可以推断出返回值类型的话,返回值类型可以省略
object Function02 {
def main(args: Array[String]): Unit = {
def fun1()="za"
println(fun1())
}
}
4.4省略参数列表
如果参数列表中没有声明任何的参数,那么参数列表可以省略,但省略之后,调用时也不能加参数列表了
object Function02 {
def main(args: Array[String]): Unit = {
def fun1="za"
println(fun1)
}
}
4.5省略等号 一般返回值类型为unit时省略
如果函数体中有明确的return语句,那么返回值类型不能省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(): String = {
return "zhangsan"
}
println(fun5())
}
}
如果函数体返回值类型明确为Unit, 那么函数体中即使有return关键字也不起作用
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(): Unit = {
return "zhangsan"
}
println(fun5())
}
}
如果函数体返回值类型声明为Unit, 但是又想省略,那么此时就必须连同等号一起省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5() {
return "zhangsan"
}
println(fun5())
}
}
4.6省略名称和关键字
省略的同时也需要将返回值类型同时省略,将等号增加一个箭头 匿名函数不能独立使用
object Function02 {
def main(args: Array[String]): Unit = {
def fun1(): String ={
"xiaobu"
}
}
}
object Function02 {
def main(args: Array[String]): Unit = {
()=>{
"xiaobu"
}
}
}
5高阶函数编程
所谓的高阶函数,其实就是将函数当成一个类型来使用,而不是当成特定的语法结构
5.1函数作为值
如果将函数作为整体,而不是将执行结果赋值给变量,那么需要采用特殊符号:下划线
之所以使用下划线让函数作为对象使用,因为代码中没有明确变量的类型,所以需要通过取值类推断
如果变量声明的类型为函数类型,那么可以不适用下划线让函数作为对象
object Function02 {
def main(args: Array[String]): Unit = {
def fun1(): String ={
"zahnsgan"
}
val a = fun1()
println(a) //zahnsgan
println("````````")
def fun2(): Unit ={
println("lisi")
}
val b = fun2() //lisi
println(b) // ()
println("````````")
def fun3(): Unit ={
println("zhangsan")
}
val c = fun3 _ //将函数对象传给c
c() //()调用函数
}
}
val c :() = > unit = fun3 这里可以省略_
5.2函数作为参数(通常会使用匿名函数)
将函数作为参数传入到函数中,记得传入参数时需去掉()即 传入函数类型的值 fun _ 或者 fun(因为知道传入的类型为函数类型,所以可以省略_)
不去掉()的话会直接执行 会将执行结果作为参数传入
如果参数在使用的时候,按照顺序只使用了一次,那么可以使用下划线代替参数
object Function02 {
def main(args: Array[String]): Unit = {
def test(f:() => Unit): Unit ={
f()
}
def fun1(): Unit ={
println("11111")
}
test(fun1)
println("****************")
def test1(f : (Int,Int) => Int): Unit ={
val i = f(10,20)
println(i)
}
def fun2(x :Int,y: Int): Int ={
x + y
}
test1(fun2)
println("****************")
def test2(f : (Int,Int) => Int): Int ={
f(10,20)
}
def fun3(x :Int,y: Int): Int ={
x + y
}
test1(fun3)
println("****************")
test1(
(x :Int,y: Int) => x + y
)
匿名函数,传入的函数名称不重要,如果只有一个参数的话可以省略,显然这里不合适
如果参数在使用的时候,按照顺序只使用了一次,那么可以使用下划线代替参数
test1(_ + _)
}
}
object Function03 {
def main(args: Array[String]): Unit = {
def test(x:Int,y:Int,f:(Int,Int)=>Int): Unit ={
println(f(x, y))
}
test(10,20,_ + _)
}
}
5.3匿名函数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4( f:Int => Int ): Int = {
f(10)
}
println(fun4((x:Int)=>{x * 20}))
println(fun4((x)=>{x * 20})) //参数类型可以推断,所以省略类型
println(fun4((x)=>x * 20)) //代码就一行 所以可以省略大括号
println(fun4(x=>x * 20)) //参数个数就一个,所以参数列表的小括号可以省略
println(fun4(_ * 20)) //参数使用时,按照顺序只使用了一次,那么可以使用下划线代替参数
}
}
5.4函数作为返回值
一般使用于内部的函数在外部使用
object Function04 {
def main(args: Array[String]): Unit = {
def outer() ={
def inner(): Unit ={
println("inner")
}
inner _
}
outer()()
}
}
5.5闭包
一个函数使用了外部的变量,把这个变量包含到了它的内部来使用,改变了这个变量的生命周期
将当前的代码形成了一个闭合的环境,这个环境称之为闭包环境,简称为闭包
1.内部函数在外部使用的时候会有闭包2.将函数作为对象使用会有闭包3.所有的匿名函数都有闭包
bject Scala06_Function_Hell_8 {
def main(args: Array[String]): Unit = {
// Scala2.12版本前闭包功能采用的是匿名函数类型实现
// Scala2.12版本闭包功能采用的是更改函数声明实现
def outer( a : Int ) = {
def inner( b : Int ): Int = {
a + b
}
inner _
}
//println(outer(10)(20))
val f = outer(10)
val ff = f(20)
println(ff)
}
}
5.6控制抽象
自己一般很少使用,传参不完成 里面函数也不完整
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun7(op: => Unit) = {
op
}
fun7{
println("xx")
}
}
}
5.7函数柯里化
声明时多个参数列表,调用时也多个参数列表
object Scala08_Function {
def main(args: Array[String]): Unit = {
// TODO 函数式编程 - 柯里化(Curry)
// 将无关的参数分离开
def test( a:Int, b:Int ): Unit = {
for ( i <- 1 to a ) { // 10min
println(i)
}
for ( j <- 1 to b ) { // 20min
println(j)
}
}
def test1(a:Int)(b:Int): Unit = {
for ( i <- 1 to a ) { // 10min
println(i)
}
for ( j <- 1 to b ) { // 20min
println(j)
}
}
val a = 10 // 10min
val b = 20 // 20min
test(a, b) // 60min
test1(a)(b)
}
}
5.8递归函数
1.scala中要求递归函数必须明确声明返回值类型
2.函数内部调用自身
3.一定要有跳出递归的逻辑
4.递归函数在调用时传递的参数之间有关系 Scala中尾递归不是真正的递归,是由编译器进行了优化,形成了while循环。所以应该称之为伪递归
// TODO 函数式编程 - 递归
def test(): Unit = {
test()
println("test")
}
test()
// 伪递归
// 尾递归
def test1(): Unit = {
println("test")
test1()
}
test1()
5.9惰性函数
当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
def fun9(): String = {
println("function...")
"zhangsan"
}
lazy val a = fun9()
println("----------")
println(a)
会推迟 println("function...")语句的输出,首次使用时,会做出输出