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 
> <[email protected]> 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 
>> <[email protected] <mailto:[email protected]>> 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>
>> 
>> 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
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to