If weak closures ever become a thing, I do think that the implicit strong 
promotion of the closure's captures should never happen and instead, the 
closure should be manually optional-unwrapped before it's called, so that the 
existing safety guarantees of weak object references would persist.

> On Jun 10, 2017, at 11:04 PM, Adrian Zubarev 
> <[email protected]> wrote:
> 
> Just a few more replies from John McCall:
> 
> You want to invalidate the closure value based on whether any of its captures 
> have been invalidated.
> 
> It’s an interesting idea, but it’s quite complex because an invalidatable 
> closure is definitely a different sort of thing from a normal one.
> 
> So like you say, it would need to be tracked in the type, which is not the 
> language model we otherwise use for closures. Er, for weak/unowned, I mean.
> 
> The behavior for unowned is not too different from the current behavior, so 
> it’s really mostly about weak.
> 
> I guess the captured reference becomes strong immediately, protecting against 
> it going away during the closure.
> 
> But unowned is conventionally used in cases where that isn’t going to happen 
> anyway.
> 
> The semantics of testing a “weak closure” are not obvious. Always must be 
> wrapped in optional, unwrapping it gives a value of non-weak type?
> 
> Totally different from normal optional behavior on values, but I guess it 
> works.
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 10. Juni 2017 um 21:58:21, Adrian Zubarev ([email protected] 
> <mailto:[email protected]>) schrieb:
> 
>> Well I simply reused the existing keywords as part of the closure type to 
>> demonstrate the idea here as easy as possible.
>> 
>> About the _true_ weak/unowned closures. First I asked John McCall on twitter 
>> about this whole idea. Here is his reply about the _true_ weak closures:
>> 
>> You mean a weak reference to a closure? No, I don’t think we’d ever want to 
>> assign closure values enough identity to give that meaning.
>> I get it, that it might be not quite obvious or even confusing why 
>> weak/unowned can be applied on a type and on a variable. However weak is 
>> always an Optional or an IUO where unowned is non-optional.
>> 
>> Just my personal thoughts: Could we potentially align weak/unowned with 
>> inout and make it type decoration? (This would be a breaking change.)
>> 
>> 
>> 
>> -- 
>> Adrian Zubarev
>> Sent with Airmail
>> 
>> Am 10. Juni 2017 um 21:44:41, Gor Gyolchanyan ([email protected] 
>> <mailto:[email protected]>) schrieb:
>> 
>>> I don't think it's a good idea to make the `weak`-ness of the closure part 
>>> of the type system.
>>> The current approach to `weak/unowned` is that it's a storage class that 
>>> applies to the variable, not the value.
>>> This makes sense because you don't *use* a weak reference, you only *store* 
>>> it weakly.
>>> I think this behavior has to stay the same with the addition of closures 
>>> (being the other reference type along classes) would be eligible for 
>>> storing by `weak/unowned` reference.
>>> 
>>>> On Jun 10, 2017, at 10:39 PM, Adrian Zubarev via swift-evolution 
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> 
>>>> Hi Matthew,
>>>> 
>>>> Thank you for the hint. Indeed, at first glance your proposal is very 
>>>> similar to my thinking. I’ll try to dive deeper into your proposal and 
>>>> find out more about the discussion behind it when I get some more time for 
>>>> that.
>>>> 
>>>> We could collaborate on a revision for Swift 5 if you would like to, but 
>>>> we wouldn’t need to rush now, because there is plenty of time for that. 
>>>> 
>>>> Personally I would love to avoid some kind of a prefix like ? if possible.
>>>> 
>>>> Brainstorming:
>>>> 
>>>> let c1 = weak someObject.method convert it to a weak closure.
>>>> 
>>>> let c2: weak (CLOSURETYPE)? = someObject.method Let the compiler do the 
>>>> job for us.
>>>> 
>>>> The latter would be great for APIs to avoid the prefix.
>>>> 
>>>> .subscribe(onNext: self.bar) weak is inferred and can be omitted 
>>>> 
>>>> 
>>>> 
>>>> 
>>>> -- 
>>>> Adrian Zubarev
>>>> Sent with Airmail
>>>> 
>>>> Am 10. Juni 2017 um 21:09:28, Matthew Johnson ([email protected] 
>>>> <mailto:[email protected]>) schrieb:
>>>> 
>>>>> 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] <mailto:[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] <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