• Scala函数式编程


    函数式编程

    面向对象编程OOP

    解决问题

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

    对象:用户

    行为:登录、JDBC、读取数据库

    属性:用户名、密码

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

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

    函数式编程

    函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 [1]

    和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。

    和过程化编程相比,函数式编程里函数的计算可随时调用。

    函数基础

    函数基本用法
    def sum(x: Int, y: Int): Int = {
        x + y
    }
    
    函数和方法的区别

    为完成某一功能的程序语句的集合,成为函数

    类中的函数称之为方法

    函数定义
    • 无参,无返回值
    • 无参,有返回值
    • 有参,无返回值
    • 有参,有返回值
    • 多参,无返回值
    • 多参,有返回值
    package chapter05
    
    object Test02_FunctionDefine {
      def main(args: Array[String]): Unit = {
        // 无参,无返回值
        def f1(): Unit = {
          println("无参,无返回值")
        }
        f1()
        println(f1())
        println("-----------------------")
    
        // 无参,有返回值
        def f2(): String = {
          println("无参,有返回值")
          return "This is f2 return value."
        }
        // f2()
        println(f2())
        println("-----------------------")
    
        // 有参,无返回值
        def f3(name: String): Unit = {
          println("有参,无返回值" + name)
        }
        println(f3("zihoo"))
        println("-----------------------")
    
        // 有参,有返回值
        def f4(name: String): String = {
          println("有参,有返回值" + name)
          return "This is f4 return value"
        }
        println(f4("zihoo"))
        println("-----------------------")
    
        // 多参,无返回值
        def f5(name1: String, name2: String): Unit = {
          println("多参,无返回值")
          println(name1 + "和" + name2 + "打招呼")
        }
        println(f5("zihoo", "gazikel"))
        println("-----------------------")
    
        // 多参,有返回值
        def f6(a: Int, b: Int): Int = {
          println("多参,有返回值")
          return a + b
        }
      }
    }
    
    函数参数
    • 可变参数
    • 如果参数列表存在多个参数,那么可变参数一般放置在最后
    • 参数默认值,一般将有默认值的参数防止在参数列表的后面
    • 带名参数,带着参数名称传值,传值就可以与顺序无关
    package chapter05
    
    object Test03_FunctionParameter {
      def main(args: Array[String]): Unit = {
        // 可变参数
        def f1(str: String*): Unit = {
          println(str)
        }
        f1("zihoo")
        f1("zihoo", "gazikel")
        println("----------------------")
    
        // 如果参数列表中存在多个参数,那么可变参数放在最后
        def f2(number: Int, str: String*): Unit = {
          println("number:" + number + ", str:" + str)
        }
        f2(10)
        println("----------------------")
    
        // 参数默认值,一般将有默认值的参数放置在参数列表的后面
        def f3(name: String = "school"): Unit = {
          println("I am at " + name)
        }
        f3()
        f3("home")
        println("----------------------")
    
        // 带名参数
        def f4(name: String, age: Int):Unit = {
          println(s"${name}${age}岁了")
        }
        f4("zihoo", 21)
        f4(age = 21, name = "zihoo")
      }
    }
    
    函数至简原则

    能省则省

    package chapter05
    
    object Test04_Simplify {
      def main(args: Array[String]): Unit = {
    
        def f0(name: String): String = {
          return name
        }
    
        // return可以省略,Scala会使用函数体的最后一行代码作为返回值
        def f1(name: String): String = {
          name
        }
    
        // 如果函数体只有一行代码,可以省略花括号
        def f2(name: String): String = name
        // 返回值类型如果能够推断出来,那么可以省略
        def f3(name: String) = name
    
        // 如果有return,则不能省略返回值类型,必须指定
        // 如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
        def f5(name:String):Unit = {
          return "这个return不起作用"
        }
        println(f5("zihoo"))
    
        // Scala如果期望是无返回值类型,可以省略等号
        def f6(name: String) {
          println("可以省略等号")
        }
    
        // 如果函数无参,但是声明了参数列表,那么调用时,小括号可加可不加
        def f7() = {
          println("f7")
        }
        f7()
        f7
    
        // 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
        def f8 {
          println("f8")
        }
        f8
    
        // 如果不关心名称,只关心逻辑处理,那么可以将函数名省略
        // 匿名函数,lambda表达式
        (name: String) => { println(name) }
      }
    }
    

    那么匿名函数连名字都没有,怎么调用呢?

    下面,详细讲述一下lambda表达式的使用。

    函数高级

    高阶函数

    函数可以作为值进行传递

    package chapter05
    
    object Test06_HighOrderFunction {
      def main(args: Array[String]): Unit = {
        def f(n: Int): Int = {
          println("f调用")
          n + 1
        }
    
        val result = f(123)
        println(result)
    
        // 函数作为值进行传递
        val f1: Int => Int = f
        val f2 = f _
        println(f1) // chapter05.Test06_HighOrderFunction$$$Lambda$5/1908923184@4563e9ab
        println(f1(23))
        println(f2) // chapter05.Test06_HighOrderFunction$$$Lambda$6/431687835@11531931
        println(f2(35))
      }
    }
    
    

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

    package chapter05
    
    object Test06_HighOrderFunction {
      def main(args: Array[String]): Unit = {
        // 函数作为参数进行传递
        // 定义二元计算函数
        def dualEval(op: (Int, Int) => Int, a: Int, b: Int): Int = {
          op(a, b)
        }
    
        def add(num1: Int, num2: Int): Int = {
          num1 + num2
        }
    
        println(dualEval(add, 1, 2))
    
        dualEval((a, b) => {
          a + b
        }, 10, 20)
      }
    }
    
    

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

    package chapter05
    
    object Test06_HighOrderFunction {
      def main(args: Array[String]): Unit = {
        // 函数可以作为函数返回值返回
        def f5(): Int => Unit = {
          def f6(a: Int): Unit = {
            println("f6调用" + a)
          }
          // 将函数直接返回
          f6
        }
    
        println(f5()) // chapter05.Test06_HighOrderFunction$$$Lambda$9/1975358023@7d417077
        f5()(26)
      }
    }
    
    
    案例实操

    对于集合的数据处理

    package chapter05
    
    object Test07_Practice_Collection {
      def main(args: Array[String]): Unit = {
    
        val arr: Array[Int] = Array(12, 45, 75, 98)
    
        // 对数据进行处理,将操作抽象出来,处理完毕的结果返回一个新的数组
        def arrayOperation(arr: Array[Int], op: Int=>Int): Array[Int] = {
          for(elem <- arr) yield op(elem)
        }
    
        // 定义一个+1操作
        def addOne(elem: Int): Int = {
          elem + 1
        }
    
        // 调用函数
        val newArray: Array[Int] = arrayOperation(arr, addOne)
        println(newArray.mkString(","))
    
        // 传入匿名函数
        val newArray2: Array[Int] = arrayOperation(arr, (elem) => elem * 2)
        println(newArray2.mkString(","))
    
      }
    }
    
    匿名函数

    没有名字的函数

    高阶函数案例
    1. 定义一个匿名函数,并将它作为值赋给变量fun。函数有三个参数,类型分别为Int, String, Char,返回值类型为Boolean

      要求调用函数fun(0, "", '0')得到返回值为false,其它情况均返回true

    2. 定义一个函数func,它接收一个Int类型的参数,返回一个函数(记作f1)。它返回的函数f1,接收一个String类型的参数,同样返回一个函数(记作f2)。行距是f2接收一个Char类型的参数,返回一个Boolean值。

      要求调用函数func(0)("")('0')得到返回值为false,其它情况均返回true

    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(1, "", '0'))
    
        def func(i: Int): String => Char => Boolean = {
          def f1(str: String): Char => Boolean = {
            def f2(c: Char): Boolean = {
              if (i == 0 && str == "" && c =='0') {
                false
              } else {
                true
              }
            }
            f2
          }
          f1
        }
      }
    }
    
    函数柯里化&闭包

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

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

    递归

    一个函数(或方法)在函数(方法)体内又调用了本身,我们称之为递归调用。

    package chapter05
    
    object Test10_Recursion {
      def main(args: Array[String]): Unit = {
        println(fact(5))
      }
    
      // 递归实现计算阶乘
      def fact(n: Int): Int = {
        if(n==1)
          1
        else
          (n - 1) * n
      }
    }
    
    控制抽象

    值调用:把计算后的值传递过去

    package chapter05
    
    object Test11_ControlAbstraction {
      def main(args: Array[String]): Unit = {
        // 传值参数
        def f0(a: Int): Unit = {
          println("a:" + a)
        }
        f0(23)
    
        def f1(): Int = {
          println("f1调用")
          12
        }
        f0(f1())
      }
    }
    

    名调用:把代码传递过去

    package chapter05
    
    object Test11_ControlAbstraction {
      def main(args: Array[String]): Unit = {
    
        def f1(): Int = {
          println("f1调用")
          12
        }
        f0(f1())
    
        println("-------------")
        // 传名参数
        def f2(a: => Int): Unit = {
          println("a:" + a)
          println("a:" + a)
        }
        f2(f1())
        
        f2({
          println("这是一个代码块")
          29
        })
      }
    }
    
    惰性函数

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

    package chapter05
    
    object Test13_Lazy {
      def main(args: Array[String]): Unit = {
        lazy val result: Int = sum(13, 47)
    
        println("1. 函数调用")
        println("2. result = " + result)
    
        def sum(a: Int, b: Int): Int = {
          println("3. sum调用")
          a + b
        }
      }
    }
    
  • 相关阅读:
    scala 数据结构(七 ):集 Set
    scala 数据结构(六):映射 Map
    scala 数据结构(五):队列 Queue
    scala 数据结构(四):列表 List
    scala 数据结构(三):元组Tuple
    scala 数据结构(二):数组
    scala 数据结构(一):数据结构简介
    Scala 面向对象(十三):隐式转换和隐式参数
    vba报表制作
    Apache与Nginx
  • 原文地址:https://www.cnblogs.com/Gazikel/p/15763818.html
Copyright © 2020-2023  润新知