Agree with Gor, this can work nicely with ownership concept.Though it will require a lot of compiler analysis, I think as Swift’s goal is to be a safer language, still worth it.
I like this idea. But yes, we need a more detail proposal, this need a lot of work. On 2017年6月10日 -0700 AM10:49, Gor Gyolchanyan via swift-evolution <[email protected]>, wrote: > The benefit that I can see here is the ability to guarantee memory safety on > API level, by way of specifying weak closure members. Previously, there way > no conceivable way of knowing that because a closure can essentially capture > whatever it wants (even the very object it's stored in), so this would be a > deterministic way of resolving *all* circular references caused by closures. > > The downside is that it would require some heavy-duty closure capture > analysis on the compiler's part, so I'd expect it to be deferred to Swift 5 > or something. > However, this does play really nicely with the ownership concept that Swift > is going for. > > I say, let's think this one through very thoroughly and write a very very > detailed proposal (including details on how would the core team get around > implementing this) and see what it looks like before submitting it. > > > On Jun 10, 2017, at 8: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] > > https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
