> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution > <swift-evolution@swift.org> wrote: > > Hello evolution folks, > > After the positive feedback on the idea of improving capturing semantics of > local functions, Alex Lynch and I worked on a proposal. Please let us know if > you have any feedback: > > https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/XXXX-improve-capture-semantics-of-local-functions.md
So, quoting the proposal: > First of all, this proposal suggests extending the requirement of the self. > prefix to local functions, but only if the local function is used as or used > inside an escaping closure. I don't love that the use of a function many lines away can cause errors in that closure. There's a "spooky action-at-a-distance" quality to this behavior that I don't like. The best idea I have is to require local functions to be annotated with `@escaping` if they're to be used in an escaping closure: func foo() { // `local1` is nonescaping since it isn't marked with the @escaping attribute. func local1() { bar() } local1() // OK, direct call { local1() }() // OK, closure is nonescaping DispatchQueue.main.async(execute: local1) // error: passing non-escaping function 'local2' to function expecting an @escaping closure DispatchQueue.main.async { local1() } // error: closure use of non-escaping function 'local2' may allow it to escape @escaping func local2() { bar() // error: call to method 'bar' in escaping local function requires explicit 'self.' to make capture semantics explicit } @escaping func local3() { self. bar() // OK, explicit `self` } DispatchQueue.main.async(execute: local3) // OK, escaping function DispatchQueue.main.async { local3() } // OK, escaping closure } func bar() { print("bar") } But this would be quite source-breaking. (Maybe it could be introduced as a warning first?) > Secondly, this proposal suggests allowing the same capture list syntax from > closures in local functions. Capture lists would still be invalid in > top-level and member functions. I think this is a good idea, but I don't like bringing the already weird use of `in` to actual functions. By analogy with the current closure syntax, the capture list ought to go somewhere before the parameter list, in one of these slots: 1. func fn<T>[foo, bar](param: T) throws -> T where T: Equatable { … } 2. func fn[foo, bar]<T>(param: T) throws -> T where T: Equatable { … } 3. func [foo, bar] fn<T>(param: T) throws -> T where T: Equatable { … } 4. [foo, bar] func fn<T>(param: T) throws -> T where T: Equatable { … } Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, and 3 just seems weird. But it seems like the one that would be easiest to misparse. -- Brent Royal-Gordon Architechies _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution