Scala函数式编程、函数基础和高阶、匿名函数、函数柯里化、闭包、递归、惰性加载

目录

函数定义、函数参数

函数至简原则 

匿名函数 

高阶函数案例

柯里化、闭包

递归 

控制抽象 

综合函数应用

惰性加载


 函数定义、函数参数

package chapter05

object Test01_FunctionAndMethod {
  def main(args: Array[String]): Unit = {
    //定义函数
    def sayHi(name:String):Unit={
      println("hi,"+name)
    }

    //调用函数
    sayHi("alice")

    //调用对象方法
    Test01_FunctionAndMethod.sayHi("bob")

    //获取对象返回值
    val result = Test01_FunctionAndMethod.sayHello("cary")
    println(result)


  }
  //定义对象的方法
  def sayHi(name:String):Unit={
    println("Hi,"+name)
  }
  def sayHello(name:String):String={
    println("Hello,"+name)
    return "hello"
  }

}
package chapter05

object Test02_FunctionDefine {
  def main(args: Array[String]): Unit = {
//    (1)	函数 1:无参,无返回值
    def f1():Unit={
    println("1:无参,无返回值")
    }
    f1()
    println(f1())
    println("-------------------------------------------")
//    (2)	函数 2:无参,有返回值
    def f2():Int={
      println("2:无参,有返回值")
      return 12
    }
    println(f2())
    println("--------------------------------------")
//    (3)	函数 3:有参,无返回值
    def f3(name:String):Unit={
      println("3:有参,无返回值"+name)
    }
    println(f3("alice"))
    println("--------------------------------------------")
//    (4)	函数 4:有参,有返回值
     def f4(name:String):String={
       println("4:有参,有返回值"+name)
       return "hi,"+name
}
    println(f4("alice"))
    println("---------------------------------")
//    (5)	函数 5:多参,无返回值
    def f5(name1:String,name2:String):Unit={
      println("5:多参,无返回值")
      println(s"${name1}和${name2}都是我的好朋友")
    }
    f5("alice","bob")
    println("------------------------------------------")

//    (6)	函数 6:多参,有返回值

    def f6(a:Int,b:Int):Int={
      println("6:多参,有返回值")
      return a+b

    }
    println(f6(12,37))

  }

}
package chapter05

object Test03_FunctionParameter {
  def main(args: Array[String]): Unit = {
//    (1)	可变参数  WrappedArray包装起来的数组 Scala抽象的集合类型
    def  f1(str:String*):Unit={
      println(str)
    }
    f1("alice")
    f1("aaa","bbb","ccc")
    println("-------------------------------------")
//    (2)	如果参数列表中存在多个参数,那么可变参数一般放置在最后  *归属于最后
    def f2(str1:String,str2:String*):Unit={
      println("str1:"+str1+"\t str2:"+str2)
    }
    f2("alice")
    f2("aaa","bbb","ccc")
    println("------------------------------------------")
//    (3)	参数默认值,一般将有默认值的参数放置在参数列表的后面
    def f3(name:String="bigdata"):Unit={
      println("my school is "+name)
    }
    f3("school")
    f3()
    println("------------------------------------------")
//    (4)	带名参数  有默认值时比较常用
    def f4(name:String="bd",age:Int):Unit={
      println(s"${age}岁的${name}在学习大数据")
    }
    f4("zhangsan",22)
    f4(age=23,name="lisi")
    f4(age=25)


  }

}

函数至简原则 

package chapter05
//函数至简原则
object Test04_Simplify {
  def main(args: Array[String]): Unit = {


    def f0(name:String):String={
      return name
    }
    println("bd")
    println("--------------------------------------")
//    (1)	return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
     def f1(name:String):String={
       name
     }
    println(f1("zs"))
    println("-------------------------------------------------")
//    (2)	如果函数体只有一行代码,可以省略花括号
    def f2(name:String):String =name
    println("zs")
    println("---------------------------------------")

//    (3)	返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
    //函数式编程 关注的就是数学上的映射关系
    def f3(name:String)=name
    println("zs")
    println("-----------------------------------")
//    (4)	如果有 return,则不能省略返回值类型,必须指定
    //要省略 一起省略
    def f4(name:String)={
    name
}
    println("bd")
    println("--------------------------------------")
//    (5)	如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
    def f5(name:String):Unit={
      return name
    }
    println("bd")
    println("--------------------------------")
//    (6)	Scala 如果期望是无返回值类型,可以省略等号
    def f6(name:String){
      println(name)
    }
//    (7)	如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
    def f7():Unit={
      println("kkxx")
    }
    f7()
    f7
    println("------------------------------")
//    (8)	如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
    def f8:Unit={
      println("kkll")
    }
    f8
    println("-------------------------------")
//    (9)	如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

    def f9(name:String):Unit={
      println(name)
    }
        //匿名函数 lambda表达式
    (name:String)=>{println(name)}

  }
}

匿名函数 

package chapter05

object Test05_Lambda {
  def main(args: Array[String]): Unit = {
    val fun=(name:String)=> {println(name)}
    fun("zhangsan")
    println("---------------------------")

    //定义一个函数,以函数作为参数输入
    def f(func:String=>Unit):Unit={
      func("lisi")
    }
    f(fun)
    f((name:String)=> {println(name)})
    println("---------------------------------")

    //匿名函数的简化原则
//    (1)	参数的类型可以省略,会根据形参进行自动的推导
    f((name)=>{
      println(name)
    })

//    (2)	类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参
//    数超过 1 的永远不能省略圆括号。
    f(name =>{
      println(name)
    })
//    (3)	匿名函数如果只有一行,则大括号也可以省略
    f(name =>println(name))
//    (4)	如果参数只出现一次,则参数省略且后面参数可以用_代替
    f(println(_))
//    (5) 如果可以推断出 当前传入的println是一个函数体 而不是调用语句 可以直接省略下划线
    f(println)


    println("-----------------------------------------")

    //实际示例,定义一个"二元运算“函数,只操作1和2两个数,但是具体运算通过参数传入

    def dualFunctionOneAndTwo(fun:(Int,Int)=>Int):Int={
      fun(1,2)  //这里1,2直接写死 只能调用1,2

    }

    val add=(a:Int,b:Int)=>a+b
    val minus=(a:Int,b:Int)=>a-b

    println(dualFunctionOneAndTwo(add))
    println(dualFunctionOneAndTwo(minus))

    println("---------------------------------")

    //匿名函数简化

    println(dualFunctionOneAndTwo((a:Int,b:Int)=>a+b))  //fun Int Int已经写死了 不用再定义Int
    println(dualFunctionOneAndTwo((a:Int,b:Int)=>a-b))

    println("---------------------------------")

    println(dualFunctionOneAndTwo((a,b)=>a+b))
    println(dualFunctionOneAndTwo(_+_))
    println(dualFunctionOneAndTwo(_-_))

    println("--------------------------------------")


    println(dualFunctionOneAndTwo((a,b)=>b-a))  //-a+b
    println(dualFunctionOneAndTwo(-_+_))
    

  }

}

高阶函数案例

package chapter05

object Test06_HighOrderFunction {
  def main(args: Array[String]): Unit = {
    def f(n:Int):Int={   //最简单的函数声明和调用
      println("f调用")
      n+1
    }

    def fun():Int={
      println("fun调用")
      1
    }

    val result:Int=f(123)
    println(result)

    fun()
    fun

    println("---------------------------------------")

    //1.函数可以作为值进行传递
    val f1:Int=>Int=f
    val f2 =f _

    println(f1)
    println(f1(12))

    println("--------------------------------------")
    println(f2)
    println(f2(35))

    println("----------------------------------------")


//    val f3=fun //引用

    //此时f3 f4 都为函数
    val f3:()=>Int=fun
    val f4=fun _
    println(f3)
    println(f4)


    println("---------------------------------------")



    //2.函数作为参数进行传递

    //定义二元计算函数
    //两个int类型的参数  得到一个int类型的返回值     传入的数据是什么
    def dualEval(op:(Int,Int)=>Int,a:Int,b:Int):Int={
      op(a,b)
    }
    def add(a:Int,b:Int):Int={
      a+b
    }

    println(dualEval(add,12,35))
    println(dualEval((a,b)=>a+b,12,35))
    println(dualEval(_+_,12,35))


    //3.函数作为函数的返回值返回
    def f5(): Int=>Unit={
      def f6(a:Int):Unit={
        println("f6调用"+a)
      }
      f6   //将函数直接返回
    }

    println(f5())  //返回的是函数f6


    println("---------------------------")


    val f6=f5()
    println(f6)
    println(f6(25))  //()是f6本身没有返回值 Unit


    println("----------------------------")

    println(f5()(25))

    

  }

}
package chapter05

object Test07_Practice_CollectionOperation {
  def main(args: Array[String]): Unit = {

    val arr:Array[Int]=Array(12,45,75,98)

    //对数组进行处理,将操作抽象出来,处理完毕之后的结果返回一个新的数组
    def arrayOperation(array:Array[Int],op:Int=>Int):Array[Int]={
      for(elem <- array) yield op(elem)
    }  //对op进行操作 返回一个新的数组



    //定义一个加一操作
    def addOne(elem:Int):Int={
      elem+1

    }

    //调用函数
    val newArray:Array[Int]=arrayOperation(arr,addOne)

    println(newArray.mkString(","))


    //传入匿名函数,实现元素翻倍
    val newArray2=arrayOperation(arr,_*2)  //(arr,elem=>elem*2)
    println(newArray2.mkString(","))



  }

}

 柯里化、闭包

package chapter05

object Test08_Practice {
  def main(args: Array[String]): Unit = {

    //练习1
    val fun =(i:Int,s:String,c:Char) =>
      {if(i==0 && s=="" && c=='0') false else true}

    println(fun(0,"",'0'))
    println(fun(0,"",'1'))
    println(fun(23,"",'0'))
    println(fun(0,"hello",'0'))


    println("------------------------------------")


    //2.练习2
    def func(i:Int):String=>(Char=>Boolean)={ //嵌套 内层函数保存下来
      def f1(s:String):Char=>Boolean ={
        def f2(c:Char):Boolean = {
          if(i==0 && s=="" && c=='0') false else true
        }
      f2
      }
    f1  //整体返回
    }

    println(func(0)("")('0'))
    println(func(0)("")('1'))
    println(func(23)("")('0'))
    println(func(0)("hello")('0'))

println("-------------------------------------")
    //匿名函数简写

    def func1(i:Int):String=>(Char=>Boolean)={
      s => c =>if(i==0 && s=="" && c=='0') false else true
    } //内层函数可以直接使用外层函数的参数的  相当于外层定义好的参数和变量 可以传递到内层函数里面去做处理
    println(func1(0)("")('0'))
    println(func1(0)("")('1'))
    println(func1(23)("")('0'))
    println(func1(0)("hello")('0'))
    //底层有相关的打包和优化时 可以放在一起 就是闭包

    println("-------------------------------------")


    //柯里化
    def func2(i:Int)(s:String)(c:Char):Boolean={
      if(i==0 && s=="" && c=='0') false else true
    }

    println(func2(0)("")('0'))
    println(func2(0)("")('1'))
    println(func2(23)("")('0'))
    println(func2(0)("hello")('0'))

  }

}

package chapter05
//闭包 柯里化
object Test09_ClosureAndCurrying {
  def main(args: Array[String]): Unit = {
    def add(a:Int,b:Int):Int={
      a+b
    }


    //1.考虑固定一个加数的场景
    def addByFour(b:Int):Int={
      4+b
    }

    //2.扩展固定加数改变的情况
    def addByFive(b:Int):Int={
      5+b
    }

    //3.将固定加数作为另一个参数传入,但是是作为“第一层参数”传入 万能钥匙->百能钥匙

    def addByFour1():Int=>Int={ //内层函数用到了外层函数的一个局部变量
      val a=4
      def addB(b:Int):Int={
        a+b

      }
      addB
    }

    def addByA(a:Int):Int=>Int ={
      def addB(b:Int):Int={
        a+b
      }
      addB
    }
    println(addByA(35)(24))

    println("----------------------------------")


    val addByFour2=addByA(4)
    val addByFive2=addByA(5)

    println(addByFour2(13))
    println(addByFive2(25))


    //4.lambda表达式简写 闭包
    def addByA1(a:Int):Int=>Int={
      (b:Int)=>{
        a+b
      }
    }

    def addByA2(a:Int):Int=>Int={
      b => a+b
    }

    def addByA3(a:Int):Int=>Int=a + _

    val addByFour3=addByA3(4)
    val addByFive3=addByA3(5)

    println(addByFour3(13))
    println(addByFive3(25))


    println("-----------------------------")

    //5.柯里化
    def addCurrying(a:Int)(b:Int):Int={   //分层调用 一旦用到柯里化 底层一定是闭包
      a+b
    }

    println(addCurrying(35)(24))

    
  }

}

递归 

package chapter05

import scala.annotation.tailrec

object Test10_Recursion {
  def main(args: Array[String]): Unit = {
    println(fact(5))
    println(tailFact(5))

  }


  //递归实现计算阶乘  纯函数编程语言可以只使用递归 但耗费栈资源
  //一次次覆盖 不耗费栈资源

  def fact(n:Int):Int={
    if(n==0) return 1
    fact(n-1)*n
  }



  //尾递归实现   java可以写成尾递归的形式 但是却是无效的 尾递归的优化是依赖编译器的
  //需要编译器知道 在栈帧里面覆盖 而不是做压栈
  //真正的函数式语言 都会支持尾递归的
  def tailFact(n:Int):Int={
    @tailrec
    def loop(n:Int,currRes: Int):Int={
      if(n==0) return currRes
      loop(n-1,currRes*n)  //把最后要做计算的*n放在了另一个参数 保存在当前乘积计算结果上面
      //在栈帧里面覆盖

    }

    loop(n,currRes = 1)

  }


}
package aa.bb
object FunctionDemo {
  //偏函数
  //"男" 、"女"、"male"、"female"  1,0
  def funPartition3:PartialFunction[String,Int]={
    case "男"=>1
    case "male"=>1
    case "女"=>0
    case "male"=>0
    case _=> -1
  }
  val arr = Array("男","女","male")
  private val strings: Array[Int] = arr.collect(funPartition3)
  println(strings.toList)


//  def funPartition2:PartialFunction[Int,String]={
//    case 1=>"优秀"
//    case 2=>"良好"
//    case 3=>"合格"
//    case 4=>"渣渣"
//    case _=>"渣渣都不如"
//  }
//  println(funPartition2(3))
//  var arr=Array(1,4,2,5,1,5,6,4,3,7,2)
//  private val strings: Array[String] = arr.collect(funPartition2)
//  println(strings.toList)


//  def funPartition:PartialFunction[String,Int]={
//    case "hello"=>1
//    case "world"=>2
//    case _=>0
//
//  }
//  val i:Int = funPartition("hello")
//  println(i)
//  val arr = Array("hello","scala","java","world")
//  val ints: Array[Int] = arr.collect(funPartition)
//  for (in<-ints){
//    println(in)
//  }



  //部分函数
//  def alarmMsg(title:String,content:String,height:Double):Unit={
      println(title+"\t"+content+":"+height)
  
    }
    alarmMsg("警报","空气甲醛浓度为",21.32d)
  
    val title:String="警报"
    def alarmMsg2=alarmMsg(title,_:String,_:Double)
    alarmMsg2("空气甲醛浓度为",21.43d)
  
    val content:String="空气甲醛浓度为"
    def alarmMsg3=alarmMsg2(content,_:Double)
    def alarmMsg4=(title,content,_:Double)
    alarmMsg3(23.12)
//  def sumResult(a:Int,b:Int):Int={
//    a+b
//  }
//
//  var num1:Int=5
//  def sum:Int=>Int=sumResult(num1,_:Int) //部分函数
//
//  println(sumResult(2,3))
//  println(sum(4))



//  //柯里化
//  def fun(a:Int,b:Int,c:Int,d:Int):Int={
//    a+b+c+d
//  }
//  def fun2(a:Int,b:Int)(c:Int,d:Int):Int={
//    a+b+c+d
//  }
  println(fun(1,2,3,4))
  private val function:(Int,Int)=>Int=fun2(1,2)
//
//  def fun3(a:Int,b:Int,c:Int)(d:Int):Int={
//    a+b+c+d
//  }
  println(fun3(1,2,3)(4))
//  def fun4(a:Int)(b:Int,c:Int,d:Int):Int={
//    a+b+c+d
//  }
  println(fun4(1)(2,3,4))
//
//  def fun5(a:Int)(b:Int)(c:Int)(d:Int):Int={
//    a+b+c+d
//  }
//  private val intToIntToIntToInt: Int => Int => Int => Int = fun5(1)
//  private val intToIntToInt: Int => Int => Int = fun5(1)(2)
//  private val intToInt: Int => Int = fun5(1)(2)(3)
//  private val i: Int = fun5(1)(2)(3)(4)
//  println(i)
//  println("----------------------------------------")


  //str1 str2 字符串拼接 拼接方法未知 通过函数来确定
  def funTest5(str1:String,str2:String,fun:(String,String)=>String):(Int,Int)=>Int={
    val result=fun(str1,str2)
    println(result,result.length)
  if(result.length>20){
    (a,b)=>a*b
  }else{
    (a,b)=>a%b
  }
  }

  private val i: Int = funTest5("hello!how are you ", "heheda",
    (str1, str2) => {
      println("str1:value " + str1 + "\n str2:value " + str2)
      str1 + "&&&&" + str2
    }
  )(246, 23)
  println(i)



/*函数作为返回值
a b c d
fun<100 fun2 else fun3
 */
//  def funTest(a:Int,b:Int,fun:(Int,Int)=>Int):(Int,Int)=>Int={
//    val result1=fun(a,b)
//    if(result1<100) {
//      println("a,b通过fun函数计算后结果小于100")
//      val sum: (Int, Int) => Int = (c, d) => c + d
//      sum
//    }
//    else {
//          println("a,b通过fun函数计算结果大于等于100")
//      (c, d) => c - d
//    }
//  }
//  val res: Int = funTest(18,30, (a, b)=>a+b)(300,100)
//  println(res)




//  def funTest3():(String,String)=>String={
//    def funDemo(str:String,str2:String):String={
//      str+"######"+str2
//    }
//     return funDemo
//  }
//  println(funTest3()("hello","scala"))
//
//
//  def funTest2(num:Int):(Int,Int)=>Int={
//    if (num%2==0){
//      val sum:(Int,Int)=>Int=(a:Int,b:Int)=>a+b
//      sum
//
//    }else{
//      val cha:(Int,Int)=>Int=(a:Int,b:Int)=>a-b
//      cha
//    }
//  }
  val fun=funTest2(13)
  val i = fun(12,21)
//  val i: Int = funTest2(13)(12,21)
//  println(i)


  //函数作为参数
//  def funTest(f:(Int,Int)=>Int):Int={
//    val a=100
//    val b=50
//    f(a,b)
//  }
//
//  val sum:(Int,Int)=>Int=(a:Int,b:Int)=>a+b
//  val ji:(Int,Int)=>Int=(a:Int,b:Int)=>a*b
//
//  def sum2(a:Int,b:Int):Int={
//    a+b
//  }
//  val result: Int = funTest(sum)
//  println(result)



//  def sum(a:Int,b:Int):Int=a+b
//
//  val abc:(Int,Int)=>Int=(a:Int,b:Int)=>{
//    println(a,b)
//    a+b
//
//  }
//
  val a:  Int               =4
//
  val abc=(a:Int,b:Int)=>a+b //匿名函数
//  val abc1=abc
//  val abc2:(Int,Int)=>Int =sum
  println(sum(1,2))
//  println(abc(1,2))
//  println(abc1(1,2))
//  println(abc2(1,2))

  //形参中带有*
//  def showMsg2(name:String,s:String*):Unit={ //不确定有多少个的时候 用*代替
      println(name)
      println(s.getClass)
      for(str<-s){
        println(str)
      }
    }
    showMsg2("gree","kb11","kb15","kb16")

//  def ji(n:Int):Int={   //5
//    if(n==1)1
//    else n*ji(n-1)    //5*(4*(3*(2*1))))
//  }
//  println(ji(1))

  //指定形参名,进行传参
//  def showMsg(name:String,age:Int):String={
//    "姓名:"+name +"年龄"+age
//  }
//  println(showMsg(age=18,name="zhangsan"))
//
//  println("-------------------------------------------------")

//  println(showMsg("gree",37))
//
//  //函数就是方法
//  def minValue(a:Int,b:Int):Int={
//    println("进入到minValue方法中")
//    if(a>b){
//      b
//    }else{
//      a
//    }
//  }
//
//  private val i: Int = minValue(12,21)
//  println(i)

  def main(args: Array[String]): Unit = {
    println("over")


  }

}

控制抽象 

package chapter05


object Test11_ControlAbstraction {
  def main(args: Array[String]): Unit = {
    //1.传值参数
    def f0(a:Int):Unit={
      println("a:"+a)
      println("a:"+a)

    }
    f0(23)


    def f1():Int={
      println("f1调用")
      12
    }
    f0(f1())

    println("-----------------------------------")

    //2.传名参数 传递的不再是具体的值,而是一部分代码块
    def f2(a: =>Int):Unit={
      println("a:"+a)
      println("a:"+a)

    }

    f2(23)
    println("-------------------------------------")
    f2(f1())  //这里并不是调用几次 执行几次 是要看传名参数的代码块
    //控制抽象 传名参数的代码块 赋给了a a执行几次  f1就会被调用几次

    println("--------------------------------")


    f2({
      println("这是一个代码块")
      29
    })
    

  }

}

综合函数应用

package chapter05

object Test12_MyWhile {
  def main(args: Array[String]): Unit = {
    var n =10

    //1.常规的while循环
    while(n>=1) {
      println(n)
      n -= 1
    }


    //2.用闭包实现一个函数,将代码块作为参数传入,递归调用

    def myWhile(condition: =>Boolean):(=>Unit)=>Unit ={
      //内层函数需要递归调用,参数就是循环体
      def doLoop(op: =>Unit):Unit={
        if(condition){
          op
          myWhile(condition)(op)
        }

      }
      doLoop _
    }

    n=10
    myWhile((n>=1))({
      println(n)
      n-=1
    })


    //3.用匿名函数实现

    def myWhile2(condition: =>Boolean):(=>Unit)=>Unit ={
      //内层函数需要递归调用,参数就是循环体
     op =>{
        if(condition){
          op
          myWhile2(condition)(op)
        }
      }

    }

    println("-------------------------------")

    n=10
    myWhile((n>=1)){
      println(n)
      n-=1
    }

    //4.用柯里化实现
    def myWhile3(condition: =>Boolean)(op :Unit):Unit = {
      if (condition) {
        op
        myWhile2(condition)(op)

      }
    }
    println("-------------------------------")

    n=10
    myWhile((n>=1)){
      println(n)
      n-=1
    }
  }

}

 惰性加载

package chapter05
//惰性求值
object Test13_Lazy {
  def main(args: Array[String]): Unit = {
    lazy val result:Int = sum(13,47)


    println("1,函数调用")
    println("2,result="+result)
    println("4,result="+result)  //已经计算出来 不需要再次计算
  }

  def sum(a: Int, b: Int):Int={
    println("3,sum调用")
    a+b
  }

}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值