> On Jun 11, 2016, at 5:18 AM, Xiaodi Wu via swift-evolution > <swift-evolution@swift.org> wrote: > > On Fri, Jun 10, 2016 at 9:55 PM, Jonathan Hull via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: > I really love this idea. My mental model of it is that it is exactly like > ‘defer’, except it works on the lifetime of the object instance instead of a > function/method. Same thing, different scope. > > I like how the creation and destruction are right next to one another. It > also solves a lot of potential issues with partial initialization, I believe. > > I might spell it ‘deferToDeinit’ or 'deferUntilDeinit' > > The only issue I see is accidentally capturing self strongly. Is there a way > to mark a closure as implicitly unowned self so the end programmer doesn’t > have to worry about it? > > I really like this idea as well. Does it need to be a regular closure? This > is one of those things that can be built into the language itself, surely? > Then the implicitly unowned self part would be taken care of...
This should be handled by the compiler and the code within the block should be used to create a deinit method. Several issues to deal with: - if there are deferred de-inits in init, is regular deinit {} allowed? If yes, does the deferred deinit code from init get called before or after? - what if there are several initializers and each has its own deferred de-inits? Would the instance need to keep the information which initializer was used and call proper deinit based on that? > > > Thanks, > Jon >> Twitter tl;dr: >> > Brent: So each instance must remember which init was used for it and then >> > run the matching deinit code at deinit time? >> > Me: In my version, the constructive act and destructive act are always >> > paired, even redundantly, using a stack if needed >> > Graham: so all your deferredDeinit blocks would run, no matter which init >> > was invoked? >> > Brent: Closure stack in the worst case. Might be able to optimize to >> > something cheaper if no captures. Degenerate case: `for i in 0..<10 { >> > deinit { print(i) } >> >> So continuing on from Twitter, assuming the compiler cannot optimize in the >> case of multiple inits, and init-redirections, how about allowing >> traditional deinit as well, and introduce compile-time optimization into >> traditional de-init if the compiler finds only one initialization path per >> class? We can also warn anyone using my version in a complicated degenerate >> way that it can be costly through education, manual, etc. It would also help >> if (especially in Cocoa), you could legally use shared initialization setup >> closures. >> >> If I create an observer, I want to be able to handle its end-of-life at that >> point. If I allocate memory, ditto. Etc etc. Surely Swift should be able to >> support doing this. >> >> -- E >> >> > On Jun 8, 2016, at 3:43 PM, Erica Sadun via swift-evolution >> > <swift-evolution at swift.org >> > <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote: >> > >> > I really like this idea. Spatially moving cleanup next to unsafe >> > operations is good practice. >> > >> > In normal code, I want my cleanup to follow as closely as possible to my >> > unsafe act: >> > >> > let buffer: UnsafeMutablePointer<CChar> = >> > UnsafeMutablePointer(allocatingCapacity: chunkSize) >> > defer { buffer.deallocateCapacity(chunkSize) } >> > >> > (Sorry for the horrible example, but it's the best I could grep up with on >> > a moment's notice) >> > >> > I like your idea but what I want to see is not the deinit child closure in >> > init you propose but a new keyword that means defer-on-deinit-cleanup >> > >> > self.ptr = UnsafeMutablePointer<T>(allocatingCapacity: count) >> > deferringDeInit { self.ptr.deallocateCapacity(count) } >> > >> > Or something. >> > >> > -- E >> > p.s. Normally I put them on the same line with a semicolon but dang these >> > things can be long >> > >> >> On Jun 8, 2016, at 10:54 AM, Graham Perks via swift-evolution >> >> <swift-evolution at swift.org >> >> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> <mailto:swift-evolution at swift.org >> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>>> wrote: >> >> >> >> Teach init a 'defer'-like ability to deinit >> >> >> >> 'defer' is a great way to ensure some clean up code is run; it's >> >> declaritive locality to the resource acquisition is a boon to clarity. >> >> >> >> Swift offers no support for resources acquired during 'init'. >> >> >> >> For an example, from >> >> https://www.mikeash.com/pyblog/friday-qa-2015-04-17-lets-build-swiftarray.html >> >> >> >> <https://www.mikeash.com/pyblog/friday-qa-2015-04-17-lets-build-swiftarray.html> >> >> >> >> <https://www.mikeash.com/pyblog/friday-qa-2015-04-17-lets-build-swiftarray.html >> >> >> >> <https://www.mikeash.com/pyblog/friday-qa-2015-04-17-lets-build-swiftarray.html>> >> >> >> >> init(count: Int = 0, ptr: UnsafeMutablePointer<T> = nil) { >> >> self.count = count >> >> self.space = count >> >> >> >> self.ptr = UnsafeMutablePointer<T>.alloc(count) >> >> self.ptr.initializeFrom(ptr, count: count) >> >> } >> >> >> >> deinit { >> >> ptr.destroy(...) >> >> ptr.dealloc(...) >> >> } >> >> >> >> Another 'resource' might be adding an NSNotificationCenter observer, and >> >> wanting to unobserve in deinit (no need in OS X 10.11, iOS 9, but for >> >> earlier releases this is a valid example). >> >> >> >> Changing the above code to use a 'defer' style deinit block might look >> >> like: >> >> >> >> init(count: Int = 0, ptr: UnsafeMutablePointer<T> = nil) { >> >> self.count = count >> >> self.space = count >> >> >> >> self.ptr = UnsafeMutablePointer<T>.alloc(count) >> >> self.ptr.initializeFrom(ptr, count: count) >> >> >> >> deinit { >> >> ptr.destroy(...) >> >> ptr.dealloc(...) >> >> } >> >> >> >> // NSNotificationCenter example too >> >> NSNotificationCenter.defaultCenter().addObserver(...) >> >> deinit { >> >> NSNotificationCenter.defaultCenter().removeObserver(...) >> >> } >> >> } >> >> >> >> The need to provide a separate implemention of deinit is gone. Reasoning >> >> for 'defer' applies here. There is good locality between what was >> >> initialized and what needs cleaning up. >> >> >> >> Considerations: >> >> 1. Should deinit blocks be invoked before or after code in an explicit >> >> deinit method? >> >> 2. Should deinit blocks be allowed in other methods; e.g. viewDidLoad()? >> >> 3. How should deinit blocks be prevented from strongly capturing self >> >> (thus preventing themselves from ever running!)? >> > > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution> > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > https://lists.swift.org/mailman/listinfo/swift-evolution > <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution