Weak references can have a non-trivial amount of overhead in high-performance code. In some cases you can guarantee that a pointer should never be null - and that if it is, a serious logic error has occcurred and you *should* crash.
I prefer crashing to running in an inconsistent state. Who knows what can happen in the latter case - data corruption? I'd prefer to crash, get a report and fix the bug. Karl This (https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email) is how I Email now > > On Sep 13, 2016 at 11:07 am, <Benjamin Spratling via swift-evolution > (mailto:[email protected])> wrote: > > > > Nick, I like where you’re headed with the instance-methods-as-closures idea. > Here’s where I’m headed with it: > > Closures are too often used to write the contents of what should be another > function, producing code similar to the “pyramid of doom” avoided by guard. I > now generally write as little code as possible in a closure, and use it > merely to dispatch out to a private function as quickly as possible. This > means I really do want classes to reference their own functions. I look at > closures more as providing the captured scope as the "void* context" that > goes along with an old C function reference, as opposed to being the scope in > which the code should be written. > > I loved the “get a closure to implicit self using nothing but the function > name” feature of Swift, but after running over a dead line by spending 1.5 > days with 3 other developers trying to find a retain cycle caused by its use, > we added it to our list of reasons to not merge code, hereafter referred to > as “the list". This from a guy who used to write flawless manual > retain/release code, back in the day. > > Incidentally, we also put “unowned" on "the list". We always use “weak” > instead. The bottom line is unowned CAN crash, and weak can’t. There is no > way to know if a call to unowned will crash or not. So we prefer to write > code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on > "the list”, and we nicknamed it the “Russian Roulette operator”) So instead > of “something like [unowned self] syntax...”, I’m suggesting “something like > [weak self] syntax..." > > So I’d prefer something like “weakself?.functionName” to produce a closure > which wraps a weak-self reference and a call to the given method if self > isn’t nil. This seems like a trivial task for the compiler when return types > are Void or Optional. Given the expectations of optional chaining, and the > zeroing behavior of any not-owned relationship, I’m not sure it makes sense > to demand a non-optional return type for a call to a parent. So I don’t think > such a feature even needs to worry about what if the expected return type > isn’t optional. > > I’d be happy to see any of the following syntaxes: > > weakself.functionName > weakself?.functionName > ?functionName > welf.functionName > self?.functionName > weak(self)?.functionName > > Obviously, one work around is to declare a protocol, and pass self, letting > the receiving class store a weak reference. But declaring protocols for every > single closure reference is a bit tedious. Literally just the back and forth > on naming them is a waste of time. And there’s the running joke that we’d > just tack “able” on the end of the method name. > > Another work around is to create several generic classes which generate > closures which weakly capture self and an unapplied method reference, and > overloaded functions or operators to provide the correct class. > Unfortunately, this still requires writing “self” explicitly, and also > explicitly writing the type of self to obtain an unapplied method reference. > > Given our experience, I would consider giving a warning when an implicit-self > closure goes into an @escaping context. > > class SomeClass { > var someFunction:(()->())? > func setup() { > prepare(closure: trigger) //this should probably be a warning > } > func prepare(closure:@escaping()->()) { > someFunction = closure > } > func trigger() { > } > } > > Self is already required when used inside an closure, for exactly this reason. > Perhaps we should require the developer to write explicit “self” or “self?” > to indicate strong or weak capture of self. > prepare(closure: self.trigger) //ok, strong self > prepare(closure: self?.trigger) //ok, weak self > Or if they would like to use unowned, > prepare(closure: RussianRoulette(self).trigger) // ;-) > > In the end, however, closures do occasionally capture non-instance-property > scope, which would need to be adapted in the wrapping closure around the call > to another method, so the number of no-adapting-needed methods may be quite > low. I expect given current priorities that this wouldn’t make it in to Swift > 3.1. But given the severity of the consequences and the simplicity of the > implementation, I would hope it would make it by Swift 4. > > -Ben Spratling > > _______________________________________________ > swift-evolution mailing list (mailto:[email protected]) > [email protected] (mailto:[email protected]) > https > (mailto:[email protected])://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
