高阶函数
* 所谓"第一等公民"(first class),指的是函数与其他数据类型一样,
* 处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,
* 或者作为别的函数的返回值。
*
高阶函数用法
* 1. 函数可以作为值进行传递 / 声明函数指针
* 语法
* var 函数指针名称: (参数类型列表) => 返回值类型 = 函数名称 _
* 示例 : var fpt: (Int, Int) => Int = sum _
* 简化
* 1. 如果参数类型列表指定,可以省略 _
* var 函数指针名称: (参数类型列表) => 返回值类型 = 函数名称
* var fpt: (Int, Int) => Int = sum
* 2. 函数名称 _ 编译器可以自动推断出 参数列表和 返回值类型,可以省略 : (参数列表) => 返回值类型
* var 函数指针名称 = 函数名称 _
* var fpt = sum _
* 注意事项
* 1. 必须定义 函数后,才能作为值赋值给变量 (函数定义必须在赋值前边)
* 使用函数指针
* 函数指针名称(实参)
*
* 2. 函数可以作为参数进行传递 / 声明 参数列表为函数指针的函数
* 语法
* def 函数名( 函数指针名称:(参数类型列表) => 返回值类型),参数名称: 参数类型 ) :返回值类型 = {
* //使用函数
* 函数指针名称(实参1,实参2)
* 函数体}
* 调用 : 函数名(函数名 _)
* 如果能够 推断出不是函数调用,可以省略 _
*
* 3. 函数可以作为返回值 / 函数的返回值类型为 函数指针
* 语法
* def 函数名(参数列表): (参数类型列表) => 返回值类型 = {
* 函数体
* return 函数名称 _
* }
* 调用
* 函数名()()
*
* 总结 :
* 函数指针类型 : (参数类型列表) => 返回值类型
* 函数指针赋值 : 函数名称 _
* 函数指针使用 : 函数指针名称(实参1,实参2)
*
* */
/**
  * @author gaocun
  * @create 2021-10-17 7:06 PM */
object 高阶函数_04 {
  /*
  * 高阶函数
  *     所谓"第一等公民"(first class),指的是函数与其他数据类型一样,
  *     处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,
  *     或者作为别的函数的返回值。
  *
  * 高阶函数用法
  *     1. 函数可以作为值进行传递 / 声明函数指针
  *       语法
  *         var 函数指针名称: (参数类型列表) => 返回值类型 = 函数名称 _
  *         示例 : var fpt: (Int, Int) => Int = sum _
  *       简化
  *         1. 如果参数类型列表指定,可以省略 _
  *             var 函数指针名称: (参数类型列表) => 返回值类型 = 函数名称
  *             var fpt: (Int, Int) => Int = sum
  *         2. 函数名称 _ 编译器可以自动推断出 参数列表和 返回值类型,可以省略 : (参数列表) => 返回值类型
  *             var 函数指针名称 = 函数名称 _
  *             var fpt = sum _
  *       注意事项
  *         1. 必须定义 函数后,才能作为值赋值给变量 (函数定义必须在赋值前边)
  *       使用函数指针
  *         函数指针名称(实参)
  *
  *     2. 函数可以作为参数进行传递 / 声明 参数列表为函数指针的函数
  *       语法
  *           def 函数名( 函数指针名称:(参数类型列表) => 返回值类型),参数名称: 参数类型 ) :返回值类型 = {
  *               //使用函数
  *               函数指针名称(实参1,实参2)
  *               函数体}
  *       调用 :  函数名(函数名 _)
  *              如果能够 推断出不是函数调用,可以省略 _
  *
  *     3. 函数可以作为返回值 / 函数的返回值类型为 函数指针
  *       语法
  *           def 函数名(参数列表): (参数类型列表) => 返回值类型 = {
  *               函数体
  *               return 函数名称 _
  *           }
  *       调用
  *          函数名()()
  *
  *    总结 :
  *       函数指针类型 : (参数类型列表) => 返回值类型
  *       函数指针赋值 : 函数名称 _
  *       函数指针使用 : 函数指针名称(实参1,实参2)
  *
  * */
  def main(args: Array[String]): Unit = {

    println("========函数可以作为值进行传递==================")

    //定义函数
    def sum(x: Int, y: Int): Int = x + y

    def mul(x: Int, y: Int): Int = x * y


    // 1. 函数可以作为值进行传递 (声明函数指针)
    // 指定参数类别列表 赋值时 _ 可以省略
    var fpt: (Int, Int) => Int = sum
    println(fpt(11, 2))

    // 赋值时 使用 _ 编译器可以自动推断出 函数参数列表 和 返回值类型
    // 声明函数指针时,这两部分可以省略
    var fpt1 = sum _
    println(fpt(11, 2))

    println("=======函数可以作为参数进行传递==============")

    def twoNumber(pt: (Int, Int) => Int, x: Int, y: Int): Int = pt(x, y)

    println(twoNumber(sum _, 1, 10))
    // 如果能够推断出来不是调用,_ 可以省略
    println(twoNumber(mul, 1, 10))

    println("========函数可以作为返回值=======================")

    def getTwoNumberFun(flag: Int) = {
      //def gap(x: Int, y: Int, z: Int) = x + y + z

      if (flag == 1) sum _
      //else if (flag == 2) gap _
      else mul _
    }

    println(getTwoNumberFun(1)(1, 2))
    println(getTwoNumberFun(2)(1, 2))

    println(getTwoNumberFun _)


  }


}