> 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

Reply via email to