Allowing `guard let self = self else { … }` for weakly captured self in a closure

Escaping self with back-ticks is an intriguing workaround for this.
However, I think escaping keywords with back-ticks for anything other than
avoiding interop naming issues should be considered an antipattern.

Allowing "guard let self = self else { return }" makes a lot of sense to me.

···

On Wed, Jan 6, 2016 at 1:18 PM, Paul Cantrell via swift-evolution < swift-evolution@swift.org> wrote:

But “self” _is_ a reserved word, and that’s the whole reason that this
proposal is necessary in the first place. If “self” were just a normal
identifier, then “if let self = self” would work just as well as “if let
foo = foo” and there would be nothing to discuss.

The docs also say "The backticks are not considered part of the
identifier; `x` and x have the same meaning." Thus `self` and self should
have the same meaning.

Well, `flurtzle` and flurtzle would have the same meaning, but `self` is
an identifier whereas as self is a keyword, so they mean different things.
That is precisely what the backticks are for.

Assigning to `self` is the same as assigning to self, which intentionally
isn't allowed.

No, you’re creating a new identifier called “self” which shadows the old
one.

Consider this:

    let foo: Int? = 7
    if let foo = foo {
        print(foo + 1)
    }

There are two identifiers named foo, one optional, one not. Both are
declared with “let”, so neither can be assigned to. But the code works.
Why? Because “let foo = foo” doesn’t assign to the outer variable; it
creates a new one. If self were not a keyword, then it would work the same
as “foo” above.

Cheers,

Paul

On Jan 6, 2016, at 2:56 PM, Jacob Bandes-Storch via swift-evolution < > swift-evolution@swift.org> wrote:

Not exactly; backticks are for making an identifier out of something
that's not normally an identifier. Most other reserved words are used in
control flow & other declarations. Rarely do they actually represent
identifiers/values that you can work with.

The docs also say "The backticks are not considered part of the
identifier; `x` and x have the same meaning." Thus `self` and self should
have the same meaning. Assigning to `self` is the same as assigning to
self, which intentionally isn't allowed. Backticks shouldn't allow you to
circumvent that.

Jacob

On Wed, Jan 6, 2016 at 12:50 PM, Paul Cantrell <paul@innig.net> wrote:

Ummm … isn’t that _exactly_ what backticks are for? From the docs:

    To use a reserved word as an identifier, put a backtick (`) before
and after it.

On Jan 5, 2016, at 10:42 PM, Greg Parker via swift-evolution < >> swift-evolution@swift.org> wrote:

I think it is a bug :-) That's not what backquotes are for. It ought to
be either supported without the backquotes or banned regardless of
backquotes.

On Jan 5, 2016, at 8:34 PM, Jacob Bandes-Storch <jtbandes@gmail.com> >> wrote:

Yes, it seems to use the strong shadowing variable. (The compiler doesn't
complain about "self.foo", and "self?.foo" becomes invalid because self is
no longer optional.)

If it weren't so useful, I'd call it a bug.

On Tue, Jan 5, 2016 at 8:34 PM, Greg Parker <gparker@apple.com> wrote:

Does further use of self after that actually use a strong shadowing
variable? Or does it go back to the weak reference it already had as if the
shadow were not there?

On Jan 5, 2016, at 8:26 PM, Jacob Bandes-Storch via swift-evolution < >>> swift-evolution@swift.org> wrote:

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@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 }

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--

*Alex Johnson | Engineering Lead*

*Quick Left, Inc. <https://quickleft.com/&gt;\*
*Boulder **|* *Denver* *|* *Portland** |** San Francisco*

1 (844) QL-NERDS

@nonsensery

<https://github.com/quickleft&gt; <Facebook;
<https://twitter.com/quickleft&gt; <https://instagram.com/quick_left/&gt;
<https://www.flickr.com/photos/quickleft&gt; <https://vimeo.com/quickleft&gt;

*What's it like to work with us? **TrainingPeaks, iTriage, and Ping
Identity share their stories in this short video** A Client's View
<https://vimeo.com/92286352&gt;\*\.

The fix is to give DeclName more teeth, which I’m considering working on. The details of the implementation aspects don’t seem important for swift-evolution though.

-Chris

···

On Jan 22, 2016, at 5:54 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Jan 22, 2016, at 17:51, Chris Lattner <clattner@apple.com> wrote:

On Jan 5, 2016, at 8:21 PM, Christopher Rogers via swift-evolution <swift-evolution@swift.org> 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 }

To confirm what others have said down thread, this is a compiler bug: this code is valid, but shouldn’t change what references to “self.method()” or “method()" bind to (i.e., explicit or implicit references to self).

Backquotes are for forming a name that happens to overlap with a keyword. In the case of `self`, this could be because you want to refer to the NSObject.`self` method for some reason. Backquotes are not a way to name self, init, subscript or any of the other declarations that look like magic identifiers.

…which we ought to fix by not reusing Identifier data for the keywords. ;-)

I suggested exactly the same thing a few days ago as [firm self]. I like
[guard self] even better.
+1

Kurt

···

On Wed, Feb 3, 2016 at 9:57 PM, Evan Maloney via swift-evolution < swift-evolution@swift.org> wrote:

I'm way-late to this discussion—I don't know how any of you get any coding
done trying to keep up with this mailing list!—but anyway...

I propose:

let doSomething: () -> Void = { [*guard* self] in
    ...
}

[guard self] would effectively work like [weak self] in that it doesn't
cause the closure itself to hold a strong reference to whatever is pointed
to by self. But if self is still around when the closure is called, it
upgrades it to a strong reference for the duration of the closure's
execution.

So, when doSomething() is just sitting around *not* doing something, it
doesn't prevent self from being deallocated.

If, by the time doSomething() is called, self is no longer there,
doSomething() just returns without the closure executing. If self *is* there,
then the closure executes with self as a strong reference inside.

That way, self within the closure is already strong, so you can use it
conveniently as a non-optional and without doing the strongSelf = self
dance. You get the memory management benefit of a weak reference without
the extra noise in your code needed to support it.

Ok, so what closures with a return value, you ask? How about something
like:

let maybeDoSomething: () -> Bool = { [guard self else false] in
    ...
}

Here, maybeDoSomething() doesn't hold a strong reference to self. If it
executes when self is still alive, the code within the braces executes with
self as a strong reference. If self is gone, the value after the else is
returned (the "return" itself is implied).

What do you think?

On Jan 28, 2016, at 7:32 PM, Hoon H. via swift-evolution < > swift-evolution@swift.org> wrote:

Thanks for your opinions.
I am writing a formal proposal, and now I think it’d be fine to elide
explicit `self` qualification after `guard let … `.

Also for your proposal, though I think mine is originated from different
intention, but final conclusion overlaps with your intention, and I am
still not sure what to do in this situation. Do you have some opinions?

— Hoon H.

On 2016/01/06, at 10:46 AM, Jacob Bandes-Storch <jtbandes@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@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@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
kurt@CircleW.org
http://www.CircleW.org/kurt/

Sorry, Kurt, I'm still slogging through old emails, or I would've given proper credit :)

As for Jerome's question of where to put the breakpoint, I'd put it in the line with the [guard self] in.

If 'self' went away before the closure executes and the guard fails, IMO the debugger should behave exactly the same as if it were entering and exiting a one-line closure, eg.:

  { return self.foo }

...except that it should do it on the line with the [guard self] regardless of how large the underlying closure is.

···

On Feb 4, 2016, at 10:41 AM, Kurt Werle <kurt@circlew.org> wrote:

I suggested exactly the same thing a few days ago as [firm self]. I like [guard self] even better.
+1

Kurt

On Wed, Feb 3, 2016 at 9:57 PM, Evan Maloney via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I'm way-late to this discussion—I don't know how any of you get any coding done trying to keep up with this mailing list!—but anyway...

I propose:

let doSomething: () -> Void = { [guard self] in
    ...
}

[guard self] would effectively work like [weak self] in that it doesn't cause the closure itself to hold a strong reference to whatever is pointed to by self. But if self is still around when the closure is called, it upgrades it to a strong reference for the duration of the closure's execution.

So, when doSomething() is just sitting around not doing something, it doesn't prevent self from being deallocated.

If, by the time doSomething() is called, self is no longer there, doSomething() just returns without the closure executing. If self is there, then the closure executes with self as a strong reference inside.

That way, self within the closure is already strong, so you can use it conveniently as a non-optional and without doing the strongSelf = self dance. You get the memory management benefit of a weak reference without the extra noise in your code needed to support it.

Ok, so what closures with a return value, you ask? How about something like:

let maybeDoSomething: () -> Bool = { [guard self else false] in
    ...
}

Here, maybeDoSomething() doesn't hold a strong reference to self. If it executes when self is still alive, the code within the braces executes with self as a strong reference. If self is gone, the value after the else is returned (the "return" itself is implied).

What do you think?

On Jan 28, 2016, at 7:32 PM, Hoon H. via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Thanks for your opinions.
I am writing a formal proposal, and now I think it’d be fine to elide explicit `self` qualification after `guard let … `.

Also for your proposal, though I think mine is originated from different intention, but final conclusion overlaps with your intention, and I am still not sure what to do in this situation. Do you have some opinions?

— Hoon H.

On 2016/01/06, at 10:46 AM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
kurt@CircleW.org
Welcome to circlew.org <Welcome to circlew.org;

What about debugging ?

How can we be sure the closure is called or not ? Where do you put the breakpoint ?

···

Le 4 févr. 2016 à 16:41, Kurt Werle via swift-evolution <swift-evolution@swift.org> a écrit :

I suggested exactly the same thing a few days ago as [firm self]. I like [guard self] even better.
+1

Kurt

On Wed, Feb 3, 2016 at 9:57 PM, Evan Maloney via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I'm way-late to this discussion—I don't know how any of you get any coding done trying to keep up with this mailing list!—but anyway...

I propose:

let doSomething: () -> Void = { [guard self] in
    ...
}

[guard self] would effectively work like [weak self] in that it doesn't cause the closure itself to hold a strong reference to whatever is pointed to by self. But if self is still around when the closure is called, it upgrades it to a strong reference for the duration of the closure's execution.

So, when doSomething() is just sitting around not doing something, it doesn't prevent self from being deallocated.

If, by the time doSomething() is called, self is no longer there, doSomething() just returns without the closure executing. If self is there, then the closure executes with self as a strong reference inside.

That way, self within the closure is already strong, so you can use it conveniently as a non-optional and without doing the strongSelf = self dance. You get the memory management benefit of a weak reference without the extra noise in your code needed to support it.

Ok, so what closures with a return value, you ask? How about something like:

let maybeDoSomething: () -> Bool = { [guard self else false] in
    ...
}

Here, maybeDoSomething() doesn't hold a strong reference to self. If it executes when self is still alive, the code within the braces executes with self as a strong reference. If self is gone, the value after the else is returned (the "return" itself is implied).

What do you think?

On Jan 28, 2016, at 7:32 PM, Hoon H. via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Thanks for your opinions.
I am writing a formal proposal, and now I think it’d be fine to elide explicit `self` qualification after `guard let … `.

Also for your proposal, though I think mine is originated from different intention, but final conclusion overlaps with your intention, and I am still not sure what to do in this situation. Do you have some opinions?

— Hoon H.

On 2016/01/06, at 10:46 AM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
kurt@CircleW.org
Welcome to circlew.org <Welcome to circlew.org;
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

If you're having that problem, I might recommend swapping in
[weak self] ...
guard self != nil...

But seriously - how often do you have a closure where self has become nil
and you wanted to see if the closure was being called?

···

On Thu, Feb 4, 2016 at 7:48 AM, Jerome ALVES <j.alves@me.com> wrote:

What about debugging ?

How can we be sure the closure is called or not ? Where do you put the
breakpoint ?

Le 4 févr. 2016 à 16:41, Kurt Werle via swift-evolution < > swift-evolution@swift.org> a écrit :

I suggested exactly the same thing a few days ago as [firm self]. I like
[guard self] even better.
+1

Kurt

On Wed, Feb 3, 2016 at 9:57 PM, Evan Maloney via swift-evolution < > swift-evolution@swift.org> wrote:

I'm way-late to this discussion—I don't know how any of you get any
coding done trying to keep up with this mailing list!—but anyway...

I propose:

let doSomething: () -> Void = { [*guard* self] in
    ...
}

[guard self] would effectively work like [weak self] in that it doesn't
cause the closure itself to hold a strong reference to whatever is pointed
to by self. But if self is still around when the closure is called, it
upgrades it to a strong reference for the duration of the closure's
execution.

So, when doSomething() is just sitting around *not* doing something, it
doesn't prevent self from being deallocated.

If, by the time doSomething() is called, self is no longer there,
doSomething() just returns without the closure executing. If self *is* there,
then the closure executes with self as a strong reference inside.

That way, self within the closure is already strong, so you can use it
conveniently as a non-optional and without doing the strongSelf = self
dance. You get the memory management benefit of a weak reference without
the extra noise in your code needed to support it.

Ok, so what closures with a return value, you ask? How about something
like:

let maybeDoSomething: () -> Bool = { [guard self else false] in
    ...
}

Here, maybeDoSomething() doesn't hold a strong reference to self. If it
executes when self is still alive, the code within the braces executes with
self as a strong reference. If self is gone, the value after the else is
returned (the "return" itself is implied).

What do you think?

On Jan 28, 2016, at 7:32 PM, Hoon H. via swift-evolution < >> swift-evolution@swift.org> wrote:

Thanks for your opinions.
I am writing a formal proposal, and now I think it’d be fine to elide
explicit `self` qualification after `guard let … `.

Also for your proposal, though I think mine is originated from different
intention, but final conclusion overlaps with your intention, and I am
still not sure what to do in this situation. Do you have some opinions?

— Hoon H.

On 2016/01/06, at 10:46 AM, Jacob Bandes-Storch <jtbandes@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@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@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
kurt@CircleW.org <kurt@circlew.org>
Welcome to circlew.org <Welcome to circlew.org;
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
kurt@CircleW.org
http://www.CircleW.org/kurt/