> On Jun 26, 2016, at 12:10 PM, Christopher Kornher via swift-evolution 
> <[email protected]> wrote:
> 
> I may be too late for Swift 3, but I am planning to propose changes to the 
> default behavior for closures capturing object references. The introduction 
> of Swift Playgrounds has raised the importance of simplifying the coding of 
> leak-free, crash-free closures. New developers should not have to understand 
> closure memory management to start writing useful and correct code.
> 
> The topic of the closure weak/strong dance has been discussed on this list 
> before. This proposal differs from previous proposals in that it will 
> eliminate the dance altogether by default. I am very interested in hearing 
> others’ opinions as to whether the benefits outweigh the costs of various 
> options.

The problem is that strong reference capture is probably the far more common 
case.

If you wanted to say that @noescape closures capture references strongly by 
default, while escaping closures capture them weakly by default that may be 
closer to reasonable for most situations but now you have magic behavior with 
an even greater cognitive overhead. (I wonder if it would be more common that 
@noescape captures strongly, escaping captures self weak by default but other 
objects strongly… of course that would have even worse cognitive overhead.)

No matter what, without a garbage collector you are stuck with sub-optimal 
solutions for fixing reference cycles. I could imagine a language feature that 
automatically detected trivial cycles (A -> B -> A) but anything more complex 
just becomes a form of garbage collection anyway.

I don’t think there is a way to square this circle. Either you have one 
“automagic” behavior that is wrong for some cases (whether strong or weak is 
the default), or you require everyone to spam their closures with explicit 
capture annotations even if there’s a default “capture everything strongly” 
variant (see C++ lambdas).

> 
> 
> Use of ‘unowned’ 
> ————————
> 
> I now routinely create closures that capture `self` and other object 
> references as ‘weak’ even if I think that I feel that `unowned ` would be 
> safe. This may not be the absolutely most performant solution, but it is 
> straightforward and robust.

I agree and our team has adopted the rule that use of unowned is not allowed 
unless the declaration is private and there is profiler proof that it 
represents a performance problem, and if used warning comments must be placed 
in the code. Weak is almost never a performance problem and eliminates the risk 
of a crash, so it is highly preferable to unowned.

I’d go so far as to say unowned should be removed; let the user use 
Unmanaged<T> if they need to capture an unowned reference. They’re entering 
expert territory anyway.



> 
> The core proposal:
> ——————
> 
> Closures capturing object references should automatically capture all object 
> references as weak.
> 

This becomes a form of the Objective-C messages-to-nil-do-nothing problem where 
you don’t crash but your closure doesn’t do any work (or does half the work!) 
because the reference(s) are/become nil. It doesn’t save you from reasoning 
about object lifetime because it is just as easy for the closure to capture the 
last reference to an object or for the lifetime to differ from the closure 
lifetime. You’re just trading reference cycles for a different problem.


> 
> 
> 2) Some of the magic in #1 could be eliminated by introducing a new capture 
> type:  ‘required’ to specify ‘weak guarded’ captures, allowing the example 
> closure to be written:
> 

This has been debated before. I support the idea of a “required” capture 
specifier but IIRC the core team was not supportive of the idea because it adds 
another layer of magic on the existing magic (object deallocated magically 
means your closure never executes).

Russ

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

Reply via email to