Hi Adrian, this is pretty similar to the Guarded Closures proposal I drafted in 
February.  This proposal needs a revision incorporating discussion feedback and 
some new ideas.  If you’re interested, here’s a link to the original discussion 
thread: 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032478.html
 
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032478.html>.

> On Jun 10, 2017, at 12:29 PM, Adrian Zubarev via swift-evolution 
> <[email protected]> wrote:
> 
> Hello Evolution,
> 
> I’d like to pitch a new idea and see where it would go. Recently I tapped 
> into a small trap and just now realized that even that non-escaping should 
> have been the default for closures (SE–0103) there is an exception for that. 
> Apparently generics don’t follow that rule and a closure like 
> 
> Optional<() -> Void> or simply (() -> Void)?
> 
> is still escaping by default. But that was the half of the story yet. As we 
> all know and “love” reference lists inside closures, methods don’t have any 
> and we have to wrap method calls into a weak referenced closure 
> 
> { [weak self] in self.foo() }
> 
> to avoid strong reference cycles. Maybe you already guess it, I accidentally 
> didn’t and tapped into the land of strong reference cycles yet again on my 
> journey.
> 
> I’d like to pitch a new way, more like a new type behavior, for closures on 
> how they could be used differently in order to avoid strong reference cycles 
> but also providing the ability to use methods without any need to wrap them.
> 
> Here is a simple code snippet using RxSwift, which will recreate my issue:
> 
> import RxSwift
> 
> let test = PublishSubject<Void>()
> 
> class A {
> 
>     let disposeBag = DisposeBag()
> 
>     func foo() {
>         test.asObservable()
>             .subscribe(onNext: self.bar) // The issue is here
>             .disposed(by: self.disposeBag)
>     }
> 
>     func bar() { print("works") }
> }
> 
> let a = A()
> a.foo()
> 
> test.onNext(()) // Testing if it works
> test.onCompleted() // Some RxSwift stuff
> In this case by passing directly the method self.bar we’re capturing self, 
> which in this situation isn’t our intention at all. To avoid this issue we 
> can simply wrap the method call into closure:
> 
> .subscribe(onNext: { [unowned self] in self.bar() })
> 
> (It’s safe to make it unowned because the dispose bag is a member of self.)
> 
> What if we had the ability for weak or unowned closures? By that I don’t mean 
> weak/unowned references to the closures themselves, because they are also 
> reference types, but an invalidation behavior for the whole closure based on 
> the _captured_ references. For instance:
> 
> let closure1: weak (() -> Void)? = { self.doWhatever() }
> 
> let closure2: weak (() -> Void)? = self.doWhatever
> 
> If one would now try to call the closure, first it will check if all the 
> captured objects are still available or not, if not the whole closure in this 
> case will simply become nil and won’t execute. In case of unowned closures it 
> will trap. Furthermore it will support the general meaning of weak/unowned 
> and will not increase the reference counter for *captured objects*.
> 
> As you have already noticed, in this case the convention is slightly 
> different because we must carry the behavior directly with the type.
> 
> func subscribe(onNext: weak ((Swift.E) -> Void)?)
> 
> If the way of my thinking is correct this idea _could maybe_ fade out the 
> very common [weak self] in guard let strongSelf = self … pattern. 
> 
> I personally cannot tell all the technical difficulties this idea might have, 
> but that’s what the evolution list is for, to collaboratively flesh out the 
> ideas if they are worth it.
> 
> If something like this could be possible it’s probably worth noting that we 
> might also be able to introduce something like @autoclosure(weak/unowned) to 
> Swift for consistency.
> 
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <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