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
