Scala 高阶函数

一、函数作为参数

  highOrderFunc是一个高阶函数,因为它可以接收一个函数作为参数

object PartialFunctionDemo {

  def main(args: Array[String]): Unit = {
    val add = (d: Double) => d + 1
    
    val res = highOrderFunc(add, 5)
    println(res)
    
  }

  def highOrderFunc(f: Double => Double, p: Double) = f(p)

}

  

二、函数作为返回值

  函数f接收一个参数n,返回一个函数(x: Double) => n - x

  f(5)(8),f(5)的返回值是一个函数,(8)是上一步返回函数的参数

def main(args: Array[String]): Unit = {
  val f = (n: Double) => (x: Double) => n - x

  val res = f(5)(8)
  println(res) // -3

}

  

三、闭包 closure

  闭包就是一个函数和与其相关的引用环境组合的一个整体。如下代码中mkSuffix函数的返回值就是一个函数,这个函数引用到了外部的suffix,它们共同组成一个闭包。好处是变量suffix一次传入,后面可以多次使用。

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

  val suffix = mkSuffix(".jpg")
  println(suffix("cat"))  // cat.jpg
  println(suffix("dog.jpg"))  // dog.jpg

}

def mkSuffix(suffix: String) = {
  (fileName: String) => if (fileName.endsWith(suffix)) fileName else fileName + suffix
}

  

四、函数科里化

  如下代码,求1到5的乘积。函数科里化可以将需要多步完成的一个函数,拆解成每步完成一件事的多个函数。这样做的好处是拆解出更加细粒度的函数,得到共用的中间结果,类似于代码封装、数仓分层的思想。

object PartialFunctionDemo {

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

    val res1 = curry01(1)(2)(3)(4)(5)
    println(res1) // 120

    val temp = curry2(1)(2)(3)
    val res2 = temp(4)(5)
    println(temp) // <function1>
    println(res2) // 120


  }

  def curry01(a: Int)(b: Int)(c: Int)(d: Int)(e: Int) = a * curry02(b)(c)(d)(e)
  def curry02(b: Int)(c: Int)(d: Int)(e: Int) = b * curry03(c)(d)(e)
  def curry03(c: Int)(d: Int)(e: Int) = c * curry04(d)(e)
  def curry04(d: Int)(e: Int) = d * curry05(e)
  def curry05(e: Int) = e

  def curry2(a: Int) = {
    b: Int => c: Int => d: Int => e: Int => a * b * c * d * e
  }
  
}

  

五、控制抽象

  函数test的参数是一个函数f,而且函数f既没有输入值也没有返回值,此时函数test就叫控制抽象

object ScalaDemo {

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

    test(f _)

  }

  def test(f: () => Unit) = {
    f()
  }

  def f = {
    println("hello")
    println("scala")
  }
  
}

  对于控制抽象函数,可以作如下简写

object ScalaDemo {

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

    //传递参数函数f时,直接传递代码块。如果只有一行,可以用小括号
    test{
      println("hello")
      println("scala")
    }
  }

  //去掉入参的小括号,: 和 => 之间有空格
  def test(f: => Unit) = {
    //调用时也去掉小括号
    f
  }

}

  利用控制抽象,实现一段循环

object ScalaDemo {

  def main(args: Array[String]): Unit = {
    var num = 10
    
    until(num > 0) {
      num -= 1
      println(num)
    }

  }

  def until(condition: => Boolean)(block: => Unit): Unit = {
    if (condition) {
      block
      //递归调用
      until(condition)(block)
    }
  }

}

  

  

 

posted @ 2020-05-02 14:15  地中有山  阅读(243)  评论(0编辑  收藏  举报