<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Twitter tl;dr: </div><div class=""></div><blockquote type="cite" class=""><div class="">Brent: So each instance must remember which init was used for it and then run the matching deinit code at deinit time?</div><div class="">Me: In my version, the constructive act and destructive act are always paired, even redundantly, using a stack if needed</div><div class="">Graham: so all your deferredDeinit blocks would run, no matter which init was invoked?</div><div class="">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) } </div></blockquote><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">-- E</div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class="">On Jun 8, 2016, at 3:43 PM, Erica Sadun via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I really like this idea. Spatially moving cleanup next to unsafe operations is good practice.</div><div class=""><br class=""></div><div class="">In normal code, I want my cleanup to follow as closely as possible to my unsafe act:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">let buffer: UnsafeMutablePointer<CChar> = UnsafeMutablePointer(allocatingCapacity: chunkSize)</font></div><div class=""><font face="Menlo" class=""> defer { buffer.deallocateCapacity(chunkSize) }</font></div></div><div class=""><br class=""></div><div class="">(Sorry for the horrible example, but it's the best I could grep up with on a moment's notice)</div><div class=""><br class=""></div><div class="">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</div><div class=""><br class=""></div><div class=""><div dir="auto" class=""><div class=""><span class="" style="background-color: rgba(255, 255, 255, 0);"><font face="Menlo" class="">self.ptr = UnsafeMutablePointer<T>(allocatingCapacity: count)</font></span></div><div class=""><span style="font-family: Menlo;" class=""> deferringDeInit { self.ptr.deallocateCapacity(count) }</span></div></div></div><div class=""><br class=""></div><div class="">Or something.</div><div class=""><br class=""></div><div class="">-- E</div><div class="">p.s. Normally I put them on the same line with a semicolon but dang these things can be long</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Jun 8, 2016, at 10:54 AM, Graham Perks via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Teach init a 'defer'-like ability to deinit<br class=""><br class="">'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.<br class=""><br class="">Swift offers no support for resources acquired during 'init'.<br class=""><br class="">For an example, from <a dir="ltr" href="https://www.mikeash.com/pyblog/friday-qa-2015-04-17-lets-build-swiftarray.html" x-apple-data-detectors="true" x-apple-data-detectors-type="link" x-apple-data-detectors-result="0" class="">https://www.mikeash.com/pyblog/friday-qa-2015-04-17-lets-build-swiftarray.html</a><br class=""><br class="">init(count: Int = 0, ptr: UnsafeMutablePointer<T> = nil) {<br class=""> self.count = count<br class=""> self.space = count<br class=""><br class=""> self.ptr = UnsafeMutablePointer<T>.alloc(count)<br class=""> self.ptr.initializeFrom(ptr, count: count)<br class="">}<br class=""><br class="">deinit {<br class=""> ptr.destroy(...)<br class=""> ptr.dealloc(...)<br class="">}<br class=""><br class="">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).<br class=""><br class="">Changing the above code to use a 'defer' style deinit block might look like:<br class=""><br class="">init(count: Int = 0, ptr: UnsafeMutablePointer<T> = nil) {<br class=""> self.count = count<br class=""> self.space = count<br class=""><br class=""> self.ptr = UnsafeMutablePointer<T>.alloc(count)<br class=""> self.ptr.initializeFrom(ptr, count: count)<br class=""><br class=""> deinit {<br class=""> ptr.destroy(...)<br class=""> ptr.dealloc(...)<br class=""> }<br class=""><br class=""> // NSNotificationCenter example too<br class=""> NSNotificationCenter.defaultCenter().addObserver(...)<br class=""> deinit { <br class=""> NSNotificationCenter.defaultCenter().removeObserver(...)<br class=""> }<br class="">}<br class=""><br class="">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.<br class=""><br class="">Considerations:<br class="">1. Should deinit blocks be invoked before or after code in an explicit deinit method?<br class="">2. Should deinit blocks be allowed in other methods; e.g. viewDidLoad()?<br class="">3. How should deinit blocks be prevented from strongly capturing self (thus preventing themselves from ever running!)?<br class=""></span></div></div></div></blockquote></div><br class=""><div class=""><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>