Scala函数

day03 Scala函数

一、创建函数

package day01
​
object Functions {
  def main(args: Array[String]): Unit = {
    //val maxF = max _的意思是将max函数赋值给名为maxF的变量,
    //但是在这里max后面添加了一个下划线 _,表示将函数的类型转换为函数值的类型
    val maxFunc = max _
    println(maxFunc(1, 2))
    println(fac(6))
    println(getIndex(Array[Int](1, 2, 3, 4), 3))
​
  }
​
  /*1、两个值找最大值*/
  def max(a:Int,b:Int):Int = {
    if(a > b) a else b
  }
​
  /*2、取绝对值*/
  def abs(a:Int):Int = {
    // -a中的-表示前缀操作符
    if(a < 0) -a else a
  }
​
  /*3、找目标值在数组中的下标位置*/
  def getIndex(arr:Array[Int],tar:Int):Int={
    // 也是用递归,循环找数组中的值,index是数组下表
    def loop(index:Int):Int={
      // 调用loop时,将index设为0,1、从第一个数查,如果相等返回当前下标
      // 2、如果不相等,index+1作为loop参数,继续调用loop
      // 3、直到数组下标超过数组长度,返回-1
      if (index >= arr.length){
        -1
        // arr(index)表示当前下标的元素值
      }else if (arr(index) == tar){
        index
      }else {
        // 继续查找对比
        loop(index+1)
      }
    }
    loop(0)
  }
​
  /*4、阶乘,使用递归(自己调自己)*/
  def fac(a:Int):Int = {
    // 递归:自己调自己
    // acc表示结果集
    def loop(n:Int,acc:Int):Int={
      if(n ==1) acc
        // 继续调用loop,形成了循环,当n减到1,直接输出结果
        // 先输入(5,1)loop(5,1)==>loop(4,5)==>loop(3,20)==>loop(2,60)==>loop(1,120)
      else loop(n-1,acc*n)
    }
    loop(a,1)
  }
  /*阶乘的另一个方法*/
  def fac1(a:Int):Int={
    if (a ==1 ) 1 else fac1(a-1)*a
  }
​
​
  def formatAbs(num: Int): Unit = {
    val msg: String = "source data = %d,abs(num)=%d"
    println(msg.format(num, abs(num)))
  }
  def formatMax(num:Int,num2:Int):Unit={
    val msg: String="source data = %d,%d,max(num)=%d"
    println(msg.format(num,num2,max(num,num2)))
  }
}

二、高阶函数--泛化函数

当一个函数被多次调用时,我们可以将这个函数写成泛化函数

/*
  * 参数列表:1、num:Int表示输入的数字
  * 2、funcName:String一个字符串
  * 3、funct:Int=>Int 定义一个方法,输入int类型,输出int类型,方法名为funct
  *    funct表示自定义的方法名,
  *    Int表示输入的参数类型,
  *    =>表示执行函数,
  *    Int表示执行完函数返回的数据类型
  *
  */
  def format(num: Int, funcName: String, funct: Int => Int): Unit = {
    // %s表示字符串占位符
    val msg = "use %s conver %d to %d"
    println(msg.format(funcName, num, funct(num)))//use max conver -2 to 2
  }

案例

package day01
​
object Functions {
  def main(args: Array[String]): Unit = {
    //val maxF = max _的意思是将max函数赋值给名为maxF的变量,
    //但是在这里max后面添加了一个下划线 _,表示将函数的类型转换为函数值的类型
    val maxFunc = max _
    println(maxFunc(1, 2))
    println(fac(6))
    println(getIndex(Array[Int](1, 2, 3, 4), 3))
​
    println("========================泛化函数转换============================")
​
    format(5,"fac函数",fac)
    format1(-3,abs)
    format2(3,2,"max",max)
  }
​
  /*1、两个值找最大值*/
  def max(a:Int,b:Int):Int = {
    if(a > b) a else b
  }
​
  /*2、取绝对值*/
  def abs(a:Int):Int = {
    // -a中的-表示前缀操作符
    if(a < 0) -a else a
  }
​
  /*3、找目标值在数组中的下标位置*/
  def getIndex(arr:Array[Int],tar:Int):Int={
    // 也是用递归,循环找数组中的值,index是数组下表
    def loop(index:Int):Int={
      // 调用loop时,将index设为0,1、从第一个数查,如果相等返回当前下标
      // 2、如果不相等,index+1作为loop参数,继续调用loop
      // 3、直到数组下标超过数组长度,返回-1
      if (index >= arr.length){
        -1
        // arr(index)表示当前下标的元素值
      }else if (arr(index) == tar){
        index
      }else {
        // 继续查找对比
        loop(index+1)
      }
    }
    loop(0)
  }
​
  /*4、阶乘,使用递归(自己调自己)*/
  def fac(a:Int):Int = {
    // 递归:自己调自己
    // acc表示结果集
    def loop(n:Int,acc:Int):Int={
      if(n ==1) acc
        // 继续调用loop,形成了循环,当n减到1,直接输出结果
        // 先输入(5,1)loop(5,1)==>loop(4,5)==>loop(3,20)==>loop(2,60)==>loop(1,120)
      else loop(n-1,acc*n)
    }
    loop(a,1)
  }
  /*阶乘的另一个方法*/
  def fac1(a:Int):Int={
    if (a ==1 ) 1 else fac1(a-1)*a
  }
​
  def form():Unit={println("=====================格式转换=======================")}
​
  def formatAbs(num: Int): Unit = {
    val msg: String = "source data = %d,abs(num)=%d"
    println(msg.format(num, abs(num)))
  }
  def formatMax(num:Int,num2:Int):Unit={
    val msg: String="source data = %d,%d,max(num)=%d"
    println(msg.format(num,num2,max(num,num2)))
  }
​
  def form1():Unit={println("=====================泛化函数:公共的转换=======================")}
​
  /*
  * 参数列表:1、num:Int表示输入的数字
  * 2、funcName:String一个字符串
  * 3、funct:Int=>Int 定义一个方法,输入int类型,输出int类型,方法名为funct
  *    funct表示自定义的方法名,
  *    Int表示输入的参数类型,
  *    =>表示执行函数,
  *    Int表示执行完函数返回的数据类型
  *
  */
  def format(num: Int, funcName: String, funct: Int => Int): Unit = {
    // %s表示字符串占位符
    val msg = "use %s conver %d to %d"
    println(msg.format(funcName, num, funct(num)))//use max conver -2 to 2
  }
​
  /**/
  def format1(num: Int, fun: Int => Int): Unit = {
    val msg = "use function conver %d to %d"
    println(msg.format(num, fun(num)))
  }
​
  /*两个参数的格式化*/
  def format2(num:Int,num2:Int,functioin:String,fun:(Int,Int)=>Int):Unit={
    val msg="%d,%d使用%s函数得出的结果为:%d"
    println(msg.format(num, num2, functioin,fun(num, num2)))
  }
}

三、高阶函数--多态函数(泛型函数)

把针对单个类型的函数运用到可以针对多个类型,函数名后面加上泛型[A]

1、正常的函数形式

package day01
​
object MultiMode {
  // 正常模式,判断数组中是否含有目标值
  def arrayContain(arr:Array[Int],tar:Int):Boolean={
    def loop(index:Int):Boolean={
      if (index >= arr.length){
        false
      }else if (arr(index) == tar){
        true
      }else{
        loop(index +1)
      }
    }
    // 使用loop函数,从索引0开始
    loop(0)
  }
​
  def main(args: Array[String]): Unit = {
    println(arrayContain(Array[Int](1,2, 3, 4, 5), 5))
  }
}
​

2、多态函数

相当于写一个模板,里面的类型用A表示,A可以是任何参数

案例1:判断一个值是否存在数组中

  /*
  * 两个参数:一个数组和一个函数
  * 1、数组中元素类型在调用时可以定义
  * 2、函数参数func:(A=>Boolean):表示这个形参func函数是输入一个A类型的数,返回Boolean类型的值
  * 但是具体怎么执行,等调用这个函数时,用具体的执行方式来替换这个形参
  * */
  def arrayMulti[A](arr:Array[A],func:A=>Boolean):Boolean={
    def loop(index:Int):Boolean={
      if (index >= arr.length){
        false
        // 表示调用这个形参返回的Boolean值,具体是什么执行方法,在调用时写出来,但不管怎么写,arr(index)就是写的函数形参的参数
      }else if (func(arr(index))){
        true
      }else{
        loop(index +1)
      }
    }
    // 使用loop函数,从索引0开始
    loop(0)
  }
​
  def main(args: Array[String]): Unit = {
    /*第二个参数应该是一个函数
    def func(x:Int):Boolean={
    if (x == 5) true
    else false
    }
    这个func咱们简写了,func在loop函数被多次循环调用时,参数x就是arr(index)
     */
    // (x: Int) => x == 5
    println(arrayMulti(Array[Int](1, 2, 3, 4), (x: Int) => x == 5))
    println(arrayMulti(Array[String]("a", "b", "c"), (x: String) => x.equals("b")))
  }

案例2:判断一个数组是否是升序(或降序)排列

package day01
​
object MultiMode {
​
  /*多态函数
  * 判断这个数组是否是升序(后降序)排列
  * */
  def multi[A](ar:Array[A],func:(A,A)=>Boolean):Boolean={
    /*
    逻辑:从索引0开始,0>= 4,false,不返回true,继续向下1<2,正确,但是前面加了!,所以还不返回,继续执行索引1
    直到 6<5,错误,取反后为true,则返回false,结果就是false
     */
    def loop(index:Int):Boolean={
        //表示查到末尾还没返回false,则整个数组就是正确的排序,中途有错误的,直接就返回false了,执行不到这里了
      if (index >= ar.length -1) true
        // 顺序正确,就取反让其不返回false,继续查找,直到顺序不正确,取反if条件就成功执行,返回了false
      else if (!func(ar(index),ar(index + 1))) false
        // 继续查找
      else loop(index + 1)
    }
    loop(0)
  }
​
  def main(args: Array[String]): Unit = {
    println(multi[Int](Array[Int](1, 2, 3, 6, 5), (x: Int, y: Int) => x <= y))
  }
}

返回值是函数的案例

  def currying(x:Int,func:(Int,Int)=>Int):Int=>Int={
    // 返回值是个函数Int=>Int,所以要传值一个Int类型的值,结果为Int类型(刚好func参数就是返回的Int值,所以借用func函数)
    // (y:Int) => func(x,y)这个就是一个匿名函数,符合返回一个函数的要求
    // 传一个Int值
    (y:Int) => func(x,y)
  }
​
  /*
  * 两个参数:1、一个A类型的数值
  * 2、一个类型A和类型B生成一个类型C的函数
  * 返回值:一个类型B生成一个类型C的函数
  * 方法体:一个匿名函数:传一个类型B的值生成(由上面函数形参func生成的类型C数据)类型C数据
  * */
  def currying1[A,B,C](a:A,func:(A,B)=>C):B=>C={
    (b:B)=>func(a,b)
  }
​
​
  def main(args: Array[String]): Unit = {
    // currying(2, (x: Int, y: Int) => x + y) 返回的这个表达式是函数
    val int_int = currying(2, (x: Int, y: Int) => x + y)
    println(int_int(4))//6
​
    val cur = currying1[Int,Int,String](5,(a:Int,b:Int)=> s"${a}${b}")
    println(cur(20))//520
  }

四、柯里化函数(Currying)

将参数分开,每个参数都形成了一个函数

作用:协助编译器进行类型推断

  /*正常函数*/
  def noCurry(x:Int,y:Int):Int={
    x + y
  }
​
  /*柯里化函数*/
  def curry(x:Int)(y:Int):Int={
    x + y
  }
​
  def main(args: Array[String]): Unit = {
    println(noCurry(2, 3))
    println(curry(1)(3))
  }

高阶案例

  /*
  * 这个函数就是柯里化函数的证明过程
  * 返回值就相当于:A=>(B=>C),因为函数是偏右法则,所以()省略了
  * A赋值1,B赋值2,流程就是:f(1)结果是一个函数(类型A生成)
  * */
  def curri[A,B,C](f:(A,B)=>C):A=> B=>C={
        // 相当于(a:A)=>{(b:B)=> f(a,b)}
    (a:A)=> (b:B)=>f(a,b)
  }
​
  /*
  * 这个函数就是柯里化函数的反证明过程
  * */
  def recurr[A,B,C](f:A=>B=>C):(A,B)=>C={
    (a:A,b:B)=> f(a)(b)
  }
​
​
  def main(args: Array[String]): Unit = {
    val func = curri[Int,Int,Int]((x:Int,y:Int)=> x+y)
    println(func)//是一个函数
    println(func(3))//也是一个函数
    println(func(3)(2))//5
  }

案例

   def arrayMulti[A](arr: Array[A])(func: A => Boolean): Boolean = {
    def loop(index: Int): Boolean = {
      if (index >= arr.length) {
        false
        // 表示调用这个形参返回的Boolean值,具体是什么执行方法,在调用时写出来,但不管怎么写,arr(index)就是写的函数形参的参数
      } else if (func(arr(index))) {
        true
      } else {
        loop(index + 1)
      }
    }
    // 使用loop函数,从索引0开始
    loop(0)
  }
  
  def main(args: Array[String]): Unit = {
​
    // 第二个参数本来应该是(x:Int=> x == 5),
    // 因为是柯里化函数,第二个参数的入参类型可以省略了
    println(arrayMulti(Array(2, 3, 4, 5, 7))(x => x == 5))
  }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值