• Scala scala函数式编程


    面向对象编程

    解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。

    Scala 语言是一个完全面向对象编程语言

    万物皆对象 对象的本质:对数据和行为的一个封装

    函数式编程

    解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用 这些封装好的步骤,解决问题

    在 Scala 中函数式编程和面向对象编程完美融合在一起了。

    函数基础

    函数和方法的区别

    (1)为完成某一功能的程序语句的集合,称为函数。

    (1)Scala 语言可以在任何的语法结构中声明任何的语法

    (2)函数没有重载和重写的概念;方法可以进行重载和重写

    (3)Scala 中函数可以嵌套定义

    函数参数

    (1)可变参数

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

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

    (4)带名参数

     def main(args: Array[String]): Unit = {
        // (1)可变参数
        def test( s : String* ): Unit = {
          println(s)
        }
        // 有输入参数:输出 Array
        test("Hello", "Scala")
        // 无输入参数:输出 List()
        test()
    
        // (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后,否则会报错
        def test2(name : String , s: String*  ): Unit = {
          println(name + "," + s)
        }
        test2("jinlian", "dalang")
    
        // (3)参数默认值
        def test3( name : String, age : Int = 30 ): Unit = {
          println(s"$name, $age")
        }
        // 如果参数传递了值,那么会覆盖默认值
        test3("jinlian", 20)
        // 如果参数有默认值,在调用的时候,可以省略这个参数
        test3("dalang")
    
        // 一般情况下,将有默认值的参数放置在参数列表的后面.否则报错
        def test4( sex : String = "男", name : String ): Unit = {
          println(s"$name, $sex")
        }
        // Scala 函数中参数传递是,从左到右
       // test4("wusong")
        //(4)带名参数
        test4(name="ximenqing")
    
      }

    函数至简原则(重点

    函数至简原则:能省则省

    (1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值

    (2)如果函数体只有一行代码,可以省略花括号

    (3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)

    (4)如果有 return,则不能省略返回值类型,必须指定

    (5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用

    (6)Scala 如果期望是无返回值类型,可以省略等号

    (7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加

    (8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略

    (9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

    def main(args: Array[String]): Unit = {
        // (0)函数标准写法
        def f( s : String ): String = {
          return s + " jinlian"
        }
        println(f("Hello"))
    
        // 至简原则:能省则省
        //(1) return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
        def f1( s : String ): String = {
          s + " jinlian"
        }
        println(f1("Hello"))
    
        //(2)如果函数体只有一行代码,可以省略花括号
        def f2(s:String):String = s + " jinlian"
        println(f2("Hello"))
    
        //(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起 省略)
        def f3( s : String ) = s + " jinlian"
        println(f3("Hello3"))
    
        //(4)如果有 return,则不能省略返回值类型,必须指定。
        def f4() :String = {
          return "ximenqing4"
        }
        println(f4())
    
        //(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也 不起作用
        def f5(): Unit = {
          return "dalang5"
        }
        println(f5())
    
        //(6)Scala 如果期望是无返回值类型,可以省略等号,加上等号之后则变为有返回值类型
        // 将无返回值的函数称之为过程
        def f6()= {
          "dalang6"
        }
        println(f6())
    
        //(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可 不加
        def f7() = "dalang7"
        println(f7())
        println(f7)
    
        //(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省 略
        def f8 = "dalang"
        //println(f8()) //不省略参数列表则会报错
        println(f8)
    
        //(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
        def f9 = (x:String)=>{println("wusong")}
        def f10(f:String=>Unit) = {
          f("")
        }
        f10(f9)
        println(f10((x:String)=>{println("wusong")}))
    
      }

    函数高级

    高阶函数

    函数可以作为值进行传递

    此处如果对于 =>的用法不理解的话可以参考 (48条消息) Scala中的 -> 与 <-以及=>,{}和()_someInNeed的博客-CSDN博客_<- scala

      def main(args: Array[String]): Unit = {
    
        //(1)调用 foo 函数,把返回值给变量 f
        //val f = foo()
        val f = foo
        println(f)
    
        //(2)在被调用函数 foo 后面加上 _,相当于把函数 foo 当成一个整体, 传递给变量 f1
        val f1 = foo _
        foo()
        f1()
    
        //(3)如果明确变量类型,那么不使用下划线也可以将函数作为整体传递给变量,此处 => 前面为参数名称,后面为返回值类型
        var f2:()=>Int = foo
        f2()
      }
      def foo():Int = {
        println("foo...")
        1
      }

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

      def main(args: Array[String]): Unit = {
        // (1)定义一个函数,函数参数还是一个函数签名;f 表示函数名称;(Int,Int) 表示输入两个 Int 参数;Int 表示函数返回值
        def f1(f: (Int, Int) => Int): Int = {
          f(2, 4)
        }
        // (2)定义一个函数,参数和返回值类型和 f1 的输入参数一致
        def add(a: Int, b: Int): Int = a + b
    
        // (3)将 add 函数作为参数传递给 f1 函数,如果能够推断出来不是调用,_ 可以省略
        println(f1(add))
        println(f1(add _))
    
      }

    函数可以作为函数返回值返回

    def f1() = {
          def f2() = {
          }
          f2 _
        }
        val f = f1()
        // 因为 f1 函数的返回值依然为函数,所以可以变量 f 可以作为函数继续调用
        f()
        // 上面的代码可以简化为
        f1()()
      }

    匿名函数

    没有名字的函数就是匿名函数。

    (x:Int)=>{函数体}

    x:表示输入参数类型;

    Int:表示输入参数类型;函数体:表示具体代码逻辑

    传递匿名函数至简原则:

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

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

    (3)匿名函数如果只有一行,则大括号也可以省略

    (4)如果参数只出现一次,则参数省略且后面参数可以用_代替

    /**
    *一个参数
    **/
    def main(args: Array[String]): Unit = {
        // (1)定义一个函数:参数包含数据和逻辑函数
        def operation(arr: Array[Int], op: Int => Int) = {
          for (elem <- arr) yield op(elem)
        }
    
        // (2)定义逻辑函数
        def op(ele: Int): Int = {
          ele + 1
        }
    
        // (3)标准函数调用
        val arr = operation(Array(1, 2, 3, 4), op)
        println(arr.mkString(","))
    
        // (4)采用匿名函数
        val arr1 = operation(Array(1, 2, 3, 4), (ele: Int) => {
          ele + 1
        })
        println(arr1.mkString(","))
    
        // (4.1)参数的类型可以省略,会根据形参进行自动的推导;
        val arr2 = operation(Array(1, 2, 3, 4), (ele) => {
          ele + 1
        })
        println(arr2.mkString(","))
    
        // (4.2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情 况:没有参数和参数超过 1 的永远不能省略圆括号。
        val arr3 = operation(Array(1, 2, 3, 4), ele => {
          ele + 1
        })
        println(arr3.mkString(","))
    
        // (4.3) 匿名函数如果只有一行,则大括号也可以省略
        val arr4 = operation(Array(1, 2, 3, 4), ele => ele + 1)
        println(arr4.mkString(","))
    
        //(4.4)如果参数只出现一次,则参数省略且后面参数可以用_代替
        val arr5 = operation(Array(1, 2, 3, 4), _ + 1)
        println(arr5.mkString(","))
    
      }

    两个参数

     def calculator(a: Int, b: Int, op: (Int, Int) => Int): Int
        = {
          op(a, b)
        }
        def op(ele: Int,ele1:Int): Int = {
          ele + ele1
        }
    
        println(calculator(1, 2, op))
    
        // (1)标准版
        println(calculator(2, 3, (x: Int, y: Int) => {x + y}))
    
        // (2)如果只有一行,则大括号也可以省略
        println(calculator(2, 3, (x: Int, y: Int) => x + y))
    
        // (3)参数的类型可以省略,会根据形参进行自动的推导;
        println(calculator(2, 3, (x , y) => x + y))
    
        // (4)如果参数只出现一次,则参数省略且后面参数可以用_代替
        println(calculator(2, 3, _ + _))
    
    
      }

    函数实例理解

     def main(args: Array[String]): Unit = {
        // (1)map 映射
        def map(arr: Array[Int], op: Int => Int) = {
          for (elem <- arr) yield op(elem)
        }
        val arr = map(Array(1, 2, 3, 4), (x: Int) => {
          x * x
        })
        println(arr.mkString(","))
    
        // (2)filter 过滤。有参数,且参数再后面只使用一次,则参数省略且 后面参数用_表示
        def filter(arr:Array[Int],op:Int =>Boolean) ={
          var arr1:ArrayBuffer[Int] = ArrayBuffer[Int]()
          for(elem <- arr if op(elem)){
            arr1.append(elem)
          }
          arr1.toArray
        }
        var arr1 = filter(Array(1, 2, 3, 4), _ % 2 == 1)
        println(arr1.mkString(","))
    
        // (3)reduce 聚合。有多个参数,且每个参数再后面只使用一次,则参 数省略且后面参数用_表示,第 n 个_代表第 n 个参数
        def reduce(arr: Array[Int], op: (Int, Int) => Int) = {
          var init: Int = arr(0)
          for (elem <- 1 until arr.length) {
            init = op(init, elem)
          }
          init
        }
        //val arr2 = reduce(Array(1, 2, 3, 4), (x, y) => x * y)
        val arr2 = reduce(Array(1, 2, 3, 4), _ * _)
        println(arr2)
        }

    函数柯里化&闭包

    没有太理解,这两个概念

    闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的 环境,称为闭包

    函数柯里化:把一个参数列表的多个参数,变成多个参数列表。

    def main(args: Array[String]): Unit = {
        def f1()={
          var a:Int = 10
          def f2(b:Int)={
            a + b
          }
          f2 _
        }
        // 在调用时,f1 函数执行完毕后,局部变量 a 应该随着栈空间释放掉
        val f = f1()
        // 但是在此处,变量 a 其实并没有释放,而是包含在了 f2 函数的内部,形成了闭合的效果
        println(f(3))
    
        println(f1()(3))
    
        // 函数柯里化,其实就是将复杂的参数逻辑变得简单化,函数柯里化一定存 在闭包
        var a:Int = 10
        def f3()(b:Int)={
          a + b
        }
        println(f3()(3))
    
    
      }

    惰性加载

    当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函 数才会执行。这种函数我们称之为惰性函数。

    注意:lazy 不能修饰 var 类型的变量

    def main(args: Array[String]): Unit = {
        lazy val res = sum(10, 30)
        println("----------------")
        println("res=" + res)
      }
      def sum(n1: Int, n2: Int): Int = {
        println("sum 被执行。。。")
        return n1 + n2
      }

    本文总结自尚硅谷Scala课件

  • 相关阅读:
    数组对象
    禁止鼠标右键保存图片、文字,禁止拖动图片等代码
    解决vscode 电脑卡顿
    vscode Html标签自动补全
    git提交报错
    作为一个程序员为什么要写博客?
    aaa
    JDBC
    去ioe
    去中心化
  • 原文地址:https://www.cnblogs.com/wfswf/p/15781750.html
Copyright © 2020-2023  润新知