• Scala学习(三)---函数式编程


    1.面向对象编程

    Scala语言是一个完全面向对象的编程语言。万物皆是对象
    对象的本质:对数据和行为的一个封装

    2. 函数式编程是什么

    在解决问题的时候,将问题分解成一个个的步骤,将每一个步骤进行封装(函数),通过调用这些封装好的步骤来解决问题。
    Scala语言是一个完全函数式编程的语言。万物皆是函数。
    函数的本质:函数可以当成一个值被传递。

    3.函数定义

    a.函数无参,无返回值

      def fun1(): Unit = {
        println("无返回值")
      }
    
    • 1
    • 2
    • 3

    b.无参,有返回值

        def fun2():String={
          "helloworld"
        }
    
    • 1
    • 2
    • 3

    c.有参,无返回值

          def fun3(name: String):Unit={
          println(s"你好,$name")
        }
    
    • 1
    • 2
    • 3

    d.有参,有返回值

        def fun4(name:String) :String={
          s"我是$name"
        }
        var str1=fun4("mao")
        println(str1)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    e.多参,无返回值

        def fun5(name:String,age:Int):Unit={
          println(s"我是$name,今年$age 岁了")
        }
    
    • 1
    • 2
    • 3

    d.多参,有返回值

        def fun6(name:String,age:Int):String={
          s"我是$name,今年$age 岁了"
        }
        var str2=fun6("mao",18);
        println(str2)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.函数参数的特殊用法

    可变参数,在参数后加*

        def sayhi(names:String*):Unit={
          println(s"hi $names")
        }
    
        sayhi()
        sayhi("zhangsan")
        sayhi("lisi","zhangsan")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    如果参数列表中存在多个参数,那么可变参数的位置一般放置在最后

        def sayhi(age:Int,names:String*):Unit={
          println(s"hi $names")
        }
    
    • 1
    • 2
    • 3

    参数默认值,一般将带有默认值的参数放置在参数列表的后面

    	//设置参数默认值
        def sayhi(names:String="mao"):Unit={
          println(s"hi $names")
        }
       sayhi()
       //将带有默认值的参数放置在参数列表最后
         def sayhi(names:String,age:Int=31):Unit={
          println(s"hi $names,$age")
        }
       sayhi("mao")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    带名参数
    如果带有默认值的参数没有放置在参数列表的最后,name在调用函数的时候,需要使用带名参数来调用

       def sayhi(age:Int=31,names:String):Unit={
          println(s"hi $names,$age")
        }
       sayhi(names = "mao")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.函数至简原则

    return可以省略,scala会使用函数体的最后一行代码最为返回值
    如果函数体只有一行代码,可以省略花括号
    返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
    如果有return,则不能省略返回值类型,必须指定
    如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
    scala如果期望是无返回值类型,可以省略等号
    如果函数式无参的,但是声明了参数列表,那么在调用的时候,小括号可加可不加
    如果函数没有参数列表,那么小括号可以省略,调用时候小括号必须省略
    如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

    6.匿名函数

    下面就是一个未化简的匿名函数的示例:

        val function1: (String, Int) => String = (name: String, age: Int) => age + name + "heihei"
        val str = function1("mao", 18)
        println(str)
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    真正的函数是这样的:

    def function1(name:String,age:Int):String={
    	age+name+"heihei"
    }
    val str = function1("mao", 18)
    println(str)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6.1 匿名函数化简原则

    参数的类型可以省略,会根据形参进行自动的推导

        //通过参数的类型推断返回值的类型
        val function2=(name:String)=>name+"heihei"
        //通过返回值的类型推断参数的类型
        val function3:String=>String= (name) => name+"heihei"
    
    • 1
    • 2
    • 3
    • 4

    类型省略之后,发现只有一个参数,则圆括号可以省略,其他情况:没有参数和参数超过1的永远不能省略圆括号。

     val function3:String=>String= name=> name+"heihei"
    
    • 1

    匿名函数如果只有一行,则大括号也可以省略
    如果参数只出现一次,则参数省略且后面参数也可以用_代替

    val function4:(Int,Int)=>Int=2*_+4*_
    
    • 1

    7.高阶函数

    7.1 函数可以作为值进行传递

      def sayHi(name:String) : String={
        println(s"hi $name")
        name
      }
    
      //此时不是作为值进行传递,而是将方法的返回值传递给了变量
      val mao:String=sayHi("mao")
    
      //此时才是将函数作为值传递
      val func1: String => String = sayHi _
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.2 函数可以作为参数进行传递

    格式如下:
    函数(函数名:(参数类型)=>返回值类型):返回值类型={}

    //示例:
      def operXY(x: Int, y: Int, func: (Int, Int) => Int): Int = {
        func(x, y)
      }
    	//调用函数,使用匿名函数作为参数值
      val countResult: Int = operXY(10, 20, (x: Int, y: Int) => x + y)//或者化简为val countResult: Int = operXY(10, 20,_+_)
    
      println(countResult)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:
    在这里插入图片描述
    通过scala语言的此特点,可以极大的简化Java语言手写MapReduce的过程

        def mapreduce(data:String,map: (String)=>Int,reduce:(Int)=>String): String = {
          //使用map读取数据
          val i = map(data)
          //走shuffle
          println("走shuffle流程")
          //对shuffle后的数据进行聚合
          val result:String=reduce(i)
          result
        }
        //调用
        mapreduce("hello world",(data:String)=>data.length,(data:Int)=>data+"reduce之后")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行结果:
    在这里插入图片描述

    7.3 函数可以作为返回值进行传递

        //函数可以作为返回值进行传递
        def sumXY(x:Int)={
          def sumY(y:Int):Int={
            x+y
          }
          //将内部定义的函数作为返回值进行返回
          sumY _
        }
    
        //提供第一个累加的数
        val func=sumXY(10)
        //提供第二个累加的数
        val result = func(20)
        println(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行结果:
    在这里插入图片描述

    7.4 柯里化写法

        //2.定于一个函数,传入三个参数c:char,s:String,i:Int
        //如果三个参数为('0',"",0),返回false,否则返回true
        def func1(c:Char):String=>(Int=>Boolean)={
          def func2(s:String):Int=>Boolean={
            def func3(i:Int):Boolean={
              (c!='0'||s!=""||i!=0)
            }
            //将func3作为返回值返回
            func3 _
          }
          //将func2作为返回值返回
          func2 _
        }
    
        val function:String=>Int=>Boolean = func1('1')
        val function1:Int=>Boolean = function("b")
        val bool:Boolean = function1(10)
        println(bool)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述
    使用柯里化写法对其进行简化:

        //柯里化写法
        def function6(c:Char)(s:String)(i:Int):Boolean={
          (c!='0'||s!=""||i!=0)
        }
        //调用
        val bool1 = function6('1')("a")(1)
        println(bool1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    PID与ADRC
    一个无竞争的缓存
    1.4 内网穿透与通知、查询用户订单
    公路平曲线及主点桩号计算
    conda中的jupyter notebook无法重命名,无法正确打开文件
    k8s快速入门教程-----3 kubernetes架构
    postgresql数据库pg_dirtyread插件闪回技术 —— 筑梦之路
    5道面试中的常见的统计学问题
    入行多年软件测试总结的经验
    解决 Android WebView 多进程导致App崩溃
  • 原文地址:https://blog.csdn.net/weixin_47109902/article/details/130614565