Scala 函數(shù)–閉包

2018-09-28 18:25 更新

函數(shù)–閉包

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

(x:Int) => x + more

這里我們引入一個(gè)自由變量 more。它不是所定義函數(shù)的參數(shù),而這個(gè)變量定義在函數(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 成為一個(gè)“閉包”,因?yàn)樗玫胶瘮?shù)外面定義的變量,定義這個(gè)函數(shù)的過(guò)程是將這個(gè)自由變量捕獲而構(gòu)成一個(gè)封閉的函數(shù)。有意思的是,當(dāng)這個(gè)自由變量發(fā)生變化時(shí),Scala 的閉包能夠捕獲到這個(gè)變化,因此 Scala 的閉包捕獲的是變量本身而不是當(dāng)時(shí)變量的值。

比如:

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

同樣的,如果變量在閉包在發(fā)生變化,也會(huì)反映到函數(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é)果還是傳遞到閉包的外面。

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

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

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)