2016-09-28 49 views
0

全局函數是具有名稱並且不捕獲任何值的閉包。爲什麼這不算作封閉捕獲?

在swift中,函數是閉包的空間形式。不同的是函數有一個名稱,如果它是一個全局函數,它不能從周圍的上下文中捕獲常量和變量。

然而,我發現,全球功能還可以捕獲從周圍的背景下也將常量和變量(請參閱下面的示例代碼)

let referenceInt = 10 

func addOne() -> Int { 
     return referenceInt + 1 //captured the constant referenceInt 
} 

let fooA = addOne 
let fooB = addOne 
let fooC = addOne 

print(fooA()) //prints 11 
print(fooB()) //prints 11 
print(fooC()) //prints 11, (func addOne captured referenceInt ?) 

print(referenceInt) //prints 10 

問題:

我相信我並沒有完全理解以下概念:

  1. 只需在操場上定義一個函數(如addOne() - >詮釋這裏)可能不意味着它是一個全球性的功能

  2. 具有「捕捉」這種情況下錯誤的認識,這是不是一個捕獲所有,(但是爲什麼)

幫助我在尋找:

我會很感激你能指出我錯誤地理解其中一部分,會更偉大的,你可以給我一些解釋。

感謝

PS:

這個問題可能是this one重複,但是,我還是將它張貼因爲沒有它沒有乾淨的答案了,我的問題,推動問題的遠一點。但是,如果您仍然想要關閉它,我尊重這一點,我願意向您學習。

回答

1

首先,我會質疑你的前提。封閉是封閉。 Swift中的所有函數都是閉包,它們都以相同的方式捕獲。

其次,我沒有看到你的代碼與捕獲或關閉有什麼關係。你在代碼中沒有做任何事情來測試是否有任何東西被捕獲。 let fooA = addOne類型的賦值沒有做任何有趣的事情,addOne中的代碼也沒有做任何有趣的事情。您只是在代碼運行時添加兩個值。當然addOne內的代碼被允許爲參考到全局變量referenceInt,但這僅僅是因爲它在範圍內。你在這裏沒有做任何事情,引發了關閉的特殊權力。

這是你的代碼的修正版,它顯示捕獲的行動:

struct Test { 
    var referenceInt = 10 

    func addOne() -> Int { 
     return referenceInt + 1 // capture 
    } 

    mutating func test() { 
     let fooA = self.addOne 
     let fooB = self.addOne 
     let fooC = self.addOne 

     referenceInt = 100 // :) 

     print(fooA()) //prints 11 
     print(fooB()) //prints 11 
     print(fooC()) //prints 11 

     print(referenceInt) //prints 100 
    } 

} 

var t = Test() 
t.test() 

我們調用fooA等前更改referenceInt。撥打fooA仍然給出11,因爲self.referenceInt的值被捕獲之前我們更改了referenceInt

+0

也許它會幫助你閱讀我的書,如果你想看看爲什麼閉包很有趣,捕捉真正需要什麼:從這裏開始:http://www.apeth.com/swiftBook/ch02.html#_closures – matt

+0

親愛的馬特,我想你指出了我的問題。是的,我有感覺,我沒有完全理解封閉,它不是封閉。我會很高興看到你的書。非常感謝您的幫助 – SLN

+1

我添加了對代碼的修改,使您可以看到捕獲的實際情況。我認爲這也證實了你的另一個直覺,那就是操場不是測試這類事情的非常有用的地方。 – matt