目录
一、函数
def hello(x:Int,y:Int): Int ={
      x + y
} 
从左到右一次为定义函数关键字 函数名 参数名 参数类型 返回值类型 第二行为函数体
二、函数和方法的区别
(1)为完成某一功能的程序语句的集合,称为函数。
(2)类中的函数称之方法。
区别:
1.函数不允许重载
2.定义在类当中的叫做方法
3.在函数当中也能够创建函数
4.在方法当中也可以定义函数
三、函数的定义格式
(1)函数1:无参,无返回值
(2)函数2:无参,有返回值
(3)函数3:有参,无返回值
(4)函数4:有参,有返回值
(5)函数5:多参,无返回值
(6)函数6:多参,有返回值
四、函数的参数
(1)可变参数
 def Hello(names:String*):Unit = { 
      println(s"hi $names")
      for (i <- names) { //可变参数在函数值本质是一个数组
        println(i)
      }
    } 
(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
def Hello(age: Int,names:String*):Unit = {
      println(s"hello $names")
    } 
(3)参数默认值,一般将有默认值的参数放置在参数列表的后面
def Hello(name:String = "KOBE"):Unit = {
      println(s"hello ${name}")
    } 
(4)带名参数
 def Hello( name:String = "KOBE" , age:Int):Unit = {
      println(s"hello ${name}")
    }
    
Hello(age = 18) 
五、函数至简原则
(1)return可以省略,Scala会使用函数体的最后一行代码作为返回值
 def hello(name:String): String ={
      (return) "KOBE"
    } 
(2)如果函数体只有一行代码,可以省略花括号
def hello01(a:Int,b:Int): Int ={
      a+b
    }
def hello01(a:Int,b:Int): Int = a+b 
(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
def hello01(a:Int,b:Int) = a+b 
(4)如果有return,则不能省略返回值类型,必须指定
def hello01(a:Int,b:Int):Int = {
      if(a < b){
        return a
      }else{
        b
      }
    } 
(5)如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
def hello01(a:Int,b:Int):Unit = return a+b 
(6)Scala如果期望是无返回值类型,可以省略等号
 def hello01(a:Int,b:Int){
      a+b
    } 
(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
 def hello01: Unit = {
      println("hello")
    }
    hello01()
    hello01 
(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
def hello01{
      println("hello")
    }
  hello01 
(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
def hello01(a:Int,b:Int) =a+b
val function: (Int, Int) => Int = (a:Int,b:Int) => a+b 
六、高阶函数
(1)函数可以作为值进行传递
def hello02(a:Int) = a
  val i: Int = hello02(10) //函数可以作为值进行传递
  val intToInt = hello02 _ //在被调用函数sayHi 后面加上 _,相当于把函数当成一个整体,传递给变量
  val hello0: Int => Int = hello02 //如果明确变量类型,那么不使用下划线也可以将函数作为整体传递给变量 
(2)函数可以作为参数进行传递
  def sum(a: Int, b: Int): Int = a + b
  def dif(a: Int, b: Int): Int = a - b
  def func(a: Int, b: Int, function: (Int, Int) => Int): Int = {
    function(a, b)
  }
  
  func(1,2,sum)
  func(1,2,dif)
  func(1,2,2 * _ / 4 *_) 
(3)函数可以作为函数返回值返回
def func01(x:Int):Int => Int = {
    def func02(y: Int): Int = {
      x + y
    }
    func02 _
  }
  val i1: Int => Int = func01(1)
  val i2: Int = i1(2)
  
  val i3: Int = func01(1)(2) 
七、匿名函数
没有名字的函数就是匿名函数
val f0: (Int, Int) => Int = (x: Int, y: Int) => x + y 
(1)参数的类型可以省略,会根据形参进行自动的推导
val f1: (Int, Int) => Int = (x, y) => x + y 
(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
val f3: Int => Int = x => x + 5 
(3)匿名函数如果只有一行,则大括号也可以省略
val f4: (Int, Int) => Int = (a, b) => a+b 
(4)如果参数只出现一次,则参数省略且后面参数可以用_代替
val f5: (Int, Int) => Int = _ + _
 
// 化简为_的条件
    // 1. 传入的参数类型可以推断 所以可以省略
    val f6: (Int, Int) => Int = (x, y) => y - x
    // 2. 参数必须只使用一次  使用的顺序必要和定义的顺序一样
    val f7: (Int, Int) => Int = -_ + _
    // 3.如果化简为匿名函数  只剩下一个_  则不可以化简
    val f8: String => String = _ + ""
    val f9: String => String = a => a
    // 4.如果化简的下划线在函数里面  也会报错
//   val f10: String => Unit = println(_ + "hi")
 
八、函数柯里化&闭包
函数柯里化:指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程
def add(x:Int,y:Int)=x+y
def add(x:Int)(y:Int) = x + y 
闭包:函数式编程标配,如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
def sumByA(a:Int)(b:Int):Int = a + b
val sumByFive1: Int => Int = sumByA(5)
val sumByFour1: Int => Int = sumByA(4) 
九、递归
@tailrec
    def func3(n:Int,result :Long):Long = {
      if (n == 1){
        result
      }else {
        func3(n - 1,result * n) //避免压栈
      }
    } 
十、控制抽象
1)值调用:把计算后的值传递过去
2)名调用:把代码传递过去
// 值调用
    def Hello(name:String):Unit = {
      println("调用hello")
      println(s"hi $name")
      println(s"hi $name")
    }
    Hello({
      println("代码块-字符串")
      "ls"
    })
    println("=======================")
// 名调用   
    def Hello01(name: => String):Unit = {
      println("调用Hello01")
      println(s"hi $name")
      println(s"hi $name")
    }
    var n = 1
    sayHi1({
      println("代码块-字符串1")
      n += 1
      "ls" + n
    })
结果:
代码块-字符串
调用hello
hi ls
hi ls
=======================
调用Hello01
代码块-字符串1
hi ls2
代码块-字符串1
hi ls3 
十一、惰性函数
当函数返回值被声明为lazy时,函数的执行将被推迟,直到首次对此取值,该函数才会执行。
def sumAB(a:Int,b:Int):Int = {
      println("函数调用")
      a + b
    }
    // 如果使用lazy关键字  在调用函数的时候  不会让函数运行
    // 需要等到使用的时候  才会去运行函数
    lazy val i: Int = sumAB(10, 20)
    println("其他代码")
    println(i)









