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

Popular posts from this blog

unity3d - Rotate an object to face an opposite direction -

angular - Is it possible to get native element for formControl? -

javascript - Why jQuery Select box change event is now working? -