Scala 闭包

在 Scala 中,闭包(Closure)是一种函数,它能够捕获并包含其定义环境中的自由变量。

闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。

闭包可以访问函数外部的变量并在函数内部使用这些变量,即使在变量的作用域已经超出其定义环境时,闭包仍然可以访问这些变量。

闭包的关键在于它可以"关闭"函数外部的变量,使得这些变量在函数内仍然可用。

如下面这段匿名的函数:

val multiplier = (i:Int) => i * 10  

函数体内有一个变量 i,它作为函数的一个参数。如下面的另一段代码:

val multiplier = (i:Int) => i * factor

在 multiplier 中有两个变量:i 和 factor。其中的一个 i 是函数的形式参数,在 multiplier 函数被调用时,i 被赋予一个新的值。然而,factor不是形式参数,而是自由变量,考虑下面代码:

var factor = 3  
val multiplier = (i:Int) => i * factor  

这里我们引入一个自由变量 factor,这个变量定义在函数外面。

这样定义的函数变量 multiplier 成为一个"闭包",因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。

完整实例

实例

object Test {  
   def main(args: Array[String]) {  
      println( "muliplier(1) value = " +  multiplier(1) )  
      println( "muliplier(2) value = " +  multiplier(2) )  
   }  
   var factor = 3  
   val multiplier = (i:Int) => i * factor  
}

运行实例 »

执行以上代码,输出结果为:

$ scalac Test.scala  
$  scala Test  
muliplier(1) value = 3  
muliplier(2) value = 6  

以下实例,closure 函数捕获了外部变量 externalVar,当 externalVar 的值改变时,闭包内的计算结果也相应改变。

实例

object ClosureExample1 {
  def main(args: Array[String]): Unit = {
    var externalVar = 10

    val closure = (x: Int) => x + externalVar

    println(closure(5))  // 输出 15

    externalVar = 20

    println(closure(5))  // 输出 25
  }
}

执行以上代码,输出结果为:

15
25

闭包作为返回值

以下实例,makeAdder 函数返回一个闭包。不同的闭包实例捕获了不同的 adder 值。

实例

object ClosureExample2 {
  def main(args: Array[String]): Unit = {
    def makeAdder(adder: Int): Int => Int = {
      (x: Int) => x + adder
    }

    val addFive = makeAdder(5)
    val addTen = makeAdder(10)

    println(addFive(3))  // 输出 8
    println(addTen(3))   // 输出 13
  }
}

执行以上代码,输出结果为:

8
13

闭包捕获变量的类型

闭包可以捕获不同类型的变量,包括值类型和引用类型。

以下实例,addMessage 闭包捕获了 messages 变量,并且可以修改它。

实例

object ClosureExample3 {
  def main(args: Array[String]): Unit = {
    var messages = List("Hello", "World")

    val addMessage = (msg: String) => messages = messages :+ msg

    addMessage("Scala")
    println(messages)  // 输出 List(Hello, World, Scala)
  }
}

执行以上代码,输出结果为:

List(Hello, World, Scala)

闭包与函数式编程

闭包在函数式编程中是一个重要的概念,广泛用于高阶函数、柯里化等技术中。

以下实例,highOrderFunction 函数接受一个函数作为参数。传递的闭包捕获了外部变量 externalVar。

实例

object ClosureExample4 {
  def main(args: Array[String]): Unit = {
    def highOrderFunction(f: Int => Int, x: Int): Int = f(x)

    val externalVar = 5
    val closure = (x: Int) => x + externalVar

    println(highOrderFunction(closure, 10))  // 输出 15
  }
}

执行以上代码,输出结果为:

15