Scala 函數(shù)–閉包

2018-09-28 18:25 更新

函數(shù)–閉包

到目前為止我們介紹的函數(shù)都只引用到傳入的參數(shù),假如我們定義如下的函數(shù):

(x:Int) => x + more

這里我們引入一個自由變量 more。它不是所定義函數(shù)的參數(shù),而這個變量定義在函數(shù)外面,比如:

var more =1

那么我們有如下的結(jié)果:

scala> var more =1
more: Int = 1
scala> val addMore = (x:Int) => x + more
addMore: Int => Int = <function1>
scala> addMore (100)
res1: Int = 101

這樣定義的函數(shù)變量 addMore 成為一個“閉包”,因為它引用到函數(shù)外面定義的變量,定義這個函數(shù)的過程是將這個自由變量捕獲而構(gòu)成一個封閉的函數(shù)。有意思的是,當這個自由變量發(fā)生變化時,Scala 的閉包能夠捕獲到這個變化,因此 Scala 的閉包捕獲的是變量本身而不是當時變量的值。

比如:

scala> more =  9999
more: Int = 9999
scala> addMore ( 10)
res2: Int = 10009

同樣的,如果變量在閉包在發(fā)生變化,也會反映到函數(shù)外面定義的閉包的值。比如:

scala> val someNumbers = List ( -11, -10, -5, 0, 5, 10)
someNumbers: List[Int] = List(-11, -10, -5, 0, 5, 10)
scala> var sum =0
sum: Int = 0
scala> someNumbers.foreach ( sum += _)
scala> sum
res4: Int = -11

可以看到在閉包中修改 sum 的值,其結(jié)果還是傳遞到閉包的外面。

如果一個閉包所訪問的變量有幾個不同的版本,比如一個閉包使用了一個函數(shù)的局部變量(參數(shù)),然后這個函數(shù)調(diào)用很多次,那么所定義的閉包應(yīng)該使用所引用的局部變量的哪個版本呢? 簡單的說,該閉包定義所引用的變量為定義該閉包時變量的值,也就是定義閉包時相當于保存了當時程序狀態(tài)的一個快照。比如我們定義下面一個函數(shù)閉包:

scala> def makeIncreaser(more:Int) = (x:Int) => x + more
makeIncreaser: (more: Int)Int => Int
scala> val inc1=makeIncreaser(1)
inc1: Int => Int = <function1>
scala> val inc9999=makeIncreaser(9999)
inc9999: Int => Int = <function1>
scala> inc1(10)
res5: Int = 11
scala> inc9999(10)
res6: Int = 10009

當你調(diào)用 makeIncreaser(1)時,你創(chuàng)建了一個閉包,該閉包定義時 more的值為 1,而調(diào)用 makeIncreaser(9999)所創(chuàng)建的閉包的 more 的值為 9999。此后你也無法修改已經(jīng)返回的閉包的 more 的值。因此 inc1 始終為加一,而 inc9999 始終為加 9999。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號