[swift-evolution] Proposal: Closures capture weak by default

Joe Groff jgroff at apple.com
Tue Dec 8 11:41:28 CST 2015


> 
> On Dec 8, 2015, at 9:28 AM, Gwendal Roué <gwendal.roue at gmail.com> wrote:
> 
> I’m really not found at all of having `let` properties captured by closures when used without explicit `self`.
> 
> Three reasons:
> 
> REASON 1. When `self` is not mandatory, then adding self should have no impact whatsoever.
> 
> Why should one add a self that is not mandatory?
> 
> 1. for symmetry (1):
> 
> 	self.foo = other.foo
> 	let delta = self.x - other.x
> 
> 2. for symmetry (2):
> 	
> 	init(a:String, index:Int) {
> 		self.name = name
> 		self.position = index+1	// keep 1-based value for implementation reasons
> 	}
> 
> 3. add your own reasons to use an explicit self even when not required, and I’m sure you did.
> 
> So generally speaking, using self when not mandatory should have no impact on the program at all.
> 
> 
> REASON 2. What happens when a property starts its life as `let`, but turns `var` eventually? For example, the property eventually becomes lazy. OK now it’s is illegal to use the property without explicit `self` in closures, and you break a bunch of code. And you need to bump the major version of your package. Just because you turn a `let foo: String` into `lazy var foo: String = …`.
> 
> That’s not good at all.
> REASON 3. It’s simply not clear. Clever, terse, smart, brilliant, but not clear.
> 
> Compare to:
> 
> 	// Obviously only `foo` is captured, and not self:
> 	let foo = self.foo
> 	performClosure { foo }


These are good points, but re: reason 2, turning a public 'let' into a 'var' is already a non-resilient, semantics-breaking change, since you're taking back a promise you made about immutability. You should publish a public 'var' with a private setter if you want to reserve the right to publish mutability in the future.

As for reason 3, the only noticeable difference between capturing an immutable property and capturing its container is that the container's lifetime might be shorter than it otherwise needs to be, so you save some memory, and weak references maybe null out sooner. If you were going to capture a weak reference to break a cycle anyway, the latter isn't a problem, and capturing the immutable value directly is preferable, since instead of disappearing, it will still be independently held by the closure.

-Joe

> My two cents.
> Gwendal Roué
> 
> 
>> Le 8 déc. 2015 à 18:01, Paul Cantrell via swift-evolution <swift-evolution at swift.org> a écrit :
>> 
>>> For 'let' properties of classes, it'd be reasonable to propose having closures capture the *property* directly by default in this way instead of capturing ‘self'
>> 
>> That would be fantastic.
>> 
>> I’ve also wondered whether there’s a tidy way for a closure to be tied to the lifecycle of self, so that when self goes away, the closure goes away too. That’s often the desired behavior. On a casual thinking through, though, it seems like a can of worms — and the “guard let self = self else { return }” proposal on another thread gives most of the same benefit.
>> 
>> P
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151208/064e1f29/attachment.html>


More information about the swift-evolution mailing list