> On Sep 13, 2016, at 10:29 AM, Benjamin Spratling via swift-evolution > <[email protected]> wrote: > > Well, then also add an unowned convenience. > But I’ve never been handed a story from UX that said, “As a user, when ____ I > want the app to crash.” > Using weak, the compiler can tell me when I’ve missed a possible case where > it’s nil.
Honestly, I’d be fine with / prefer only allowing unowned (at all) if it’s @noescape, if that, requiring strong or weak for anything that escapes. That seems to go along with swift’s emphasis on safety. > But the point here is to get closure references that don’t create retain > cycles. Obviously, there’s desire for both weak and unowned variants without > the syntactic overhead of a full closure. > >> On Sep 13, 2016, at 12:22 PM, Karl Wagner <[email protected] >> <mailto:[email protected]>> wrote: >> >> 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 >>> <http://lists.swift.org/mailman/listinfo/swift-evolution> > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
