[swift-evolution] Allowing `guard let self = self else { ... }` for weakly captured self in a closure.

Jacob Bandes-Storch jtbandes at gmail.com
Tue Jan 5 22:26:50 CST 2016


Wow! I didn't know that worked. It's a bit surprising, and perhaps not
intended. I think the proposal is still valid.

On Tue, Jan 5, 2016 at 8:21 PM, Christopher Rogers <christorogers at gmail.com>
wrote:

> You can shadow self with a guard like you wrote it if use the keyword
> escaping backquotes like so:
>
> guard let `self` = self else { return }
> On Wed, Jan 6, 2016 at 10:55 AM Jacob Bandes-Storch via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> FWIW, in a codebase of ~150 Swift files, I see 18 occurrences of "let
>> strongSelf = self", and 26 occurrences of "self?." (which should arguably
>> be changed to the former).
>>
>> Jacob
>>
>> On Tue, Jan 5, 2016 at 5:46 PM, Jacob Bandes-Storch <jtbandes at gmail.com>
>> wrote:
>>
>>> +1.
>>>
>>> Merely using "self?.something" repeatedly might produce unexpected
>>> behavior, if self becomes nil between calls. As I mentioned in another
>>> thread, in Obj-C, there is a warning for this (-Warc-repeated-use-of-weak).
>>>
>>> In many cases, I use the pattern
>>>
>>>     somethingAsync { [weak self] in
>>>         guard let strongSelf = self else { return }
>>>
>>>         // use strongSelf below
>>>     }
>>>
>>> But of course, this leads to the unnatural/unwieldy
>>> "strongSelf.property" all over the place.
>>>
>>> I agree with Jordan that "guard let self = self" isn't the most
>>> satisfying syntax, but it has the advantage of being a *very* minimal
>>> grammar/syntax change, and its behavior is completely clear as long as the
>>> user is already familiar with guard.
>>>
>>> We should also consider whether "self." is required after "guard let
>>> self = self". An explicit "guard let self = self" avoids the
>>> accidental-capture problem, so I think it's reasonable to allow unqualified
>>> property access for the remainder of the scope.
>>>
>>> Jacob
>>>
>>> On Tue, Jan 5, 2016 at 4:20 PM, Jordan Rose via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>>> This has come up before, in a thread called "Proposal: weakStrong self
>>>> in completion handler closures". I'm still not 100% happy with the
>>>> syntax, but I like that "guard let" can handle non-Void non-Optional
>>>> returns well, while 'weakStrong' cannot.
>>>>
>>>> Jordan
>>>>
>>>>
>>>> On Jan 5, 2016, at 16:02, Hoon H. via swift-evolution <
>>>> swift-evolution at swift.org> wrote:
>>>>
>>>> Currently, weakly captured `self` cannot be bound to `guard let …` with
>>>> same name, and emits a compiler error.
>>>>
>>>> class Foo {
>>>> func test2(f: ()->()) {
>>>> // …
>>>> }
>>>> func test1() {
>>>> test2 { [weak self] in
>>>> guard let self = self else { return } // Error.
>>>> print(self)
>>>> }
>>>> }
>>>> }
>>>>
>>>> Do we have any reason to disallow making `self` back to strong
>>>> reference? It’d be nice if I can do it. Please consider this case.
>>>>
>>>> class Foo {
>>>> func getValue1() -> Int {
>>>> return 1234
>>>> }
>>>> func test3(value: Int) {
>>>> print(value)
>>>> }
>>>> func test2(f: ()->()) {
>>>> // …
>>>> }
>>>> func test1() {
>>>> test2 { [weak self] in
>>>> self?.test3(self?.getValue1()) // Doesn't work because it's not
>>>> unwrapped.
>>>>
>>>> self!.test3(self!.getValue1()) // Considered harmful due to `!`.
>>>>
>>>> guard self != nil else { return }
>>>> self!.test3(self!.getValue1()) // OK, but still looks and feels harmful.
>>>>
>>>> guard let self1 = self else { return }
>>>> self1.test3(self1.getValue1()) // OK, but feels ugly due to unnecessary
>>>> new name `self1`.
>>>>
>>>> guard let self = self else { return }
>>>> self.test3(self.getValue1()) // OK.
>>>>
>>>> }
>>>> }
>>>> }
>>>>
>>>> This also can be applied to `if let` or same sort of constructs.
>>>>
>>>> Even further, we can consider removing required reference to `self`
>>>> after `guard let …` if appropriate.
>>>>
>>>> guard let self = self else { return }
>>>> test3(getValue1()) // Referencing to `self` would not be required
>>>> anymore. Seems arguable.
>>>>
>>>> I think this is almost fine because users have to express their
>>>> intention explicitly with `guard` statement. If someone erases the `guard`
>>>> later, compiler will require explicit self again, and that will prevent
>>>> mistakes. But still, I am not sure this removal would be perfectly fine.
>>>>
>>>> I am not sure whether this is already supported or planned. But lacked
>>>> at least in Swift 2.1.1.
>>>>
>>>> — Hoon H.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>
>>>>
>>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160105/fceb4446/attachment.html>


More information about the swift-evolution mailing list