В старом быстром мире (2.0 я считаю) у меня был реализация следующих Y-комбинаторIssue пропускание замыкания, которое принимает ускользающее замыкание на функцию, которая принимает закрытие этого типа
func Y<T, R>(f: (T -> R) -> (T -> R)) -> (T -> R) {
return { (t: T) -> R in
return f(self.Y(f))(t)
}
}
Я бы назвал У-расческа других рекурсивное закрытия, например, так:
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()
идея заключается в том, что, как наблюдатель от уведомлению «SendData» получил свои ответы, он направляет уведомление в класс, охватывающий мой Y- комбинатор и повторное замыкание. После того, как все экземпляры наблюдателя уведомления «SendData» получили свои данные,
self.responses_received == responses_expected
бы быть правдой, и мы не будем называть п раз().
Теперь, мой вопрос заключается в том, что переход на Swift 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 тег. Это компилируется, но он чувствует себя не так, и я на самом деле не проверял, действительно ли это действие будет работать во время выполнения.
Что мне здесь не хватает?
A-ha, это было именно это, спасибо вам большое! – agreendev