ios - Issue passing a closure that takes an escaping closure to a function that accepts a closure of that type -
in old swift world (2.0 believe) had following y-combinator implementation
func y<t, r>( f: (t -> r) -> (t -> r) ) -> (t -> r) { return { (t: t) -> r in return f(self.y(f))(t) } }
i call y-comb elsewhere create recursive closure, so:
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()
the idea being observer of 'senddata' notification received responses, he'd send notification class encompassing y-combinator , repeating closure. once instances of observer of 'senddata' notification have received data,
self.responses_received == responses_expected
would true, , wouldn't call f() again.
now, issue conversion swift 3.0 has forced me explicitly declare type of 'f' @escaping, on definition of y so:
func y<t, r>( _ f: @escaping ((t) -> r) -> ((t) -> r) ) -> ((t) -> r) { return { (t: t) -> r in return f(self.y(f))(t) } }
and subsequently converted repeating closure have same type. fine, understand difference between @escaping , @noescape , why code needs it. however, when attempting build compile error types not matching:
cannot convert value of type '(@escaping () -> ()) -> (() -> ())' expected argument type '(() -> ()) -> (() -> ())'
i've created simple example closure test gives same error:
let innerclosure = { (f: @escaping ()->()) -> (()->()) in return {} } let repeatclosure = self.y(innerclosure)
whereas following has no issue:
let innerclosure = { (f: ()->()) -> (()->()) in return {} } let repeatclosure = self.y(innerclosure)
i suggestion fixit force cast type, sans @escaping tag. compiles, feels wrong , haven't tested whether cast work @ run time.
what missing here?
your y
function should have following signature:
func y<t, r>(_ f: @escaping (@escaping (t) -> r) -> ((t) -> r)) -> ((t) -> r)
since accepts escaping function needs escaping function.
when call y
, closure should start with:
self.y { (f: @escaping () -> ()) -> (() -> ()) in
notice @escaping
corresponds second escaping in y
signature. mismatch on @escaping
causing compiler error.
most of rest should sort out (once update dispatch , nsnotificationcenter calls swift 3).
Comments
Post a Comment