[swift-evolution] A shortcut for weakly referencing functions

Radosław Pietruszewski radexpl at gmail.com
Fri Apr 1 11:26:27 CDT 2016


>> Here’s a pattern I find myself doing quite often:
>> 
>>  1> class Child {
>>  2.     var onSomeEvent: () -> Void = { }
>>  3. }
>>  4> class Parent {
>>  5.     let child = Child()
>>  6.     init() {
>>  7.         child.onSomeEvent = doSomething
>>  8.     }
>>  9.     func doSomething() {
>> 10.     }
>> 11. }
>> 
>> I have some ownership hierarchy of classes (often controllers — view
>> controllers — views), where I pass information from children up to
>> parents using closures set by the parent.
>> 
>> I like this pattern because children classes don’t have to be tied to
>> knowledge about their parents, and I don’t have to define delegate
>> protocols. It’s very clean, and also very easy to set up.
>> 
>> The only problem is that there’s a strong danger of introducing reference
>> cycles.
>> 
>> With class properties, you can quite easily see the potential for a
>> reference cycle and mark references to parents with weak/unowned. And
>> with `self` captures in closures, you’re reminded of memory management by
>> having to be explicit about `self`. But when passing references from
>> parents to children, there’s no way to mark the closure property as
>> `weak` (and there’s no reminder of the danger).
> 
> I will go ahead and note, at least in terms of writing the proposal, I
> don't find this argument very strong. The proposed syntax still requires
> you to know about the cycles involved.

Oh, I agree. The proposal doesn’t fix the relative undiscoverability (is that a word?) of the potential for reference cycles when passing function references.

Still — I think, maybe, when you can say in tutorials and programming guides that you avoid reference cycles when passing functions down the ownership hierarchy by wrapping those function references in #weak(…) / #unowned(…), it might be easier to grasp and remember than `{ [unowned self] in self.foo($0) }`.

> 
>> 
>> * * *
>> 
>> Right now, every time I pass a closure down to children, I have to wrap
>> my references like so:
>> 
>> 	{ [unowned self] self.doSomething($0) }
>> 
>> instead of a neat and simple function reference:
>> 
>> 	doSomething
>> 
>> I think it would be useful to have a shortcut syntax for creating weak
>> and unowned references to functions, like so:
>> 
>> 	@unowned(doSomething)
>> 
>> or perhaps:
>> 
>> 	#unowned(self.doSomething)
>> 
>> * * *
> 
> I really like the #unowned syntax! It's expressive and in line with
> other pieces of Swift sugar. Would +1 if it came to a proposal!
> 
> The @ version doesn't make as much sense as it's not an attribute.

Thank you. You’re probably right about #unowned(…) vs @unowned(…). I thought of at-syntax because it feels like applying an attribute to the function reference. (IIRC, weak and unowned were @weak and @unowned in Swift β1)

> 
>> 
>> An alternative would be the ability to mark closure properties as weak or
>> unowned. Then I could, at the *child* level, say:
>> 
>> 	unowned let onSomeEvent: () -> Void
> 
> I don't particularly think it makes sense, because it is prescriptive.
> If some other user in your codebase wanted the cycle, they couldn't get
> it. Plus, what would it mean when the closure isn't capturing anything?

Rright. Because it’s not really about assigning literal closures to such a parameter, rather assigning method references, where the method’s receiver (self in my example) is implicitly captured… So it seems like it should be a responsibility of the code assigning the reference.

— Radek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160401/7e3fd70a/attachment.html>


More information about the swift-evolution mailing list