2016-09-22 58 views
0

在舊SWIFT世界的封閉(2.0我相信)的功能,我有以下的Y組合子實現問題傳遞閉包需要一個逃避關閉,以接受該類型

func Y<T, R>(f: (T -> R) -> (T -> R)) -> (T -> R) { 
    return { (t: T) -> R in 
     return f(self.Y(f))(t) 
    } 
} 

我會打電話在Y梳子別處創建一個遞歸的關閉,像這樣:

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))) 
let repeatClosure = self.Y { 
    (f:() ->()) -> (() ->()) in 
    return { 
     if self.responses_received != responses_expected { 
      dispatch_after(delayTime, dispatch_get_main_queue()) {       
       // Resend 
       NSNotificationCenter.defaultCenter(). 
        postNotificationName(sendData, 
        object: nil, userInfo: dataToSend) 

       f() 
      } 
     } else { 
      print("Completed!") 
      self.responses_received = 0 
     } 
    } 
} 

repeatClosure() 

的想法是,作爲「送出數據」的通知觀察員收到了他的回覆,他會發送通知,要求類涵蓋我Y-組合子和重複關閉。一旦「送出數據」的通知觀察員的所有實例都收到了他們的數據,

self.responses_received == responses_expected 

將是真實的,並且我們不會()再次調用F。

現在,我的問題是,轉換爲雨燕3.0已經迫使我明確聲明「F」的類型爲@escaping,Y上的,像這樣的定義:

func Y<T, R>(_ f: @escaping ((T) -> R) -> ((T) -> R)) -> ((T) -> R) { 
    return { (t: T) -> R in 
     return f(self.Y(f))(t) 
    } 
} 

,隨後轉化我重複關閉有相同的類型。這很好,我理解@escaping和@noescape之間的區別以及爲什麼我的代碼需要它。然而,試圖建立時,我得到一個編譯錯誤,關於不匹配的類型:

Cannot convert value of type '(@escaping() ->()) -> (() ->())' 
to expected argument type '(() ->()) -> (() ->())' 

我創建了一個簡單的實例關閉只是爲了測試與給出了同樣的錯誤:

let innerClosure = { (f: @escaping()->()) -> (()->()) in 
    return {} 
} 

let repeatClosure = self.Y(innerClosure) 

而以下是沒有問題的:

let innerClosure = { (f:()->()) -> (()->()) in 
    return {} 
} 

let repeatClosure = self.Y(innerClosure) 

我從fixit得到了強制轉換類型的建議,沒有使用@escaping標記。這個編譯,但它感覺錯了,我沒有真正測試,演員是否會在運行時真正工作。

我在這裏錯過了什麼?

回答

1

Y功能應具有以下特徵:

func Y<T, R>(_ f: @escaping (@escaping (T) -> R) -> ((T) -> R)) -> ((T) -> R) 

因爲它接受一個避開功能本身需要一個避開功能。

當你調用Y,封閉的開頭爲:

self.Y { (f: @escaping() ->()) -> (() ->()) in 

通知,這@escaping對應Y簽名逃逸。這是導致你的編譯器錯誤的這個@escaping不匹配。

其餘大部分應該自行排除(一旦你更新調度和NSNotificationCenter調用Swift 3)。

+0

阿哈,這就是它,非常感謝你! – agreendev

0

我在操場此代碼,它建立沒有任何問題:

class Foo { 
    func Y<T,R>(_ f: @escaping ((T) -> R) -> ((T) -> R)) -> ((T) -> R) { 
    return { (t: T) -> R in 
     return f(self.Y(f))(t) 
    } 
    } 

    func test() { 
    let innerClosure = { (f:()->()) -> (()->()) in 
     print("test") 
     return {} 
    } 

    let repeatClosure = self.Y(innerClosure) 
    repeatClosure() 
    } 
} 

Foo().test() // prints "test" 

你可能要清理你的構建,並重新嘗試構建了,因爲我沒有得到我在操場上那個fixit來建議。