2016-09-22 25 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来建议。