2021.12.1Scala函数式编程、函数基础和高阶

2021.12.1Scala函数式编程、函数基础和高阶,第1张

2021.12.1Scala函数式编程、函数基础和高阶
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 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
  }

}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5636978.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存