> On Feb 22, 2017, at 4:57 PM, David Hedbor <neot...@gmail.com> wrote: > > > > > On Wed, Feb 22, 2017 at 2:23 PM, Matthew Johnson <matt...@anandabits.com > <mailto:matt...@anandabits.com>> wrote: > >> On Feb 22, 2017, at 4:06 PM, David Hedbor <neot...@gmail.com >> <mailto:neot...@gmail.com>> wrote: >> >> One more thing I'd like to add into the discussion is handling of optional >> variables. My assumption is that if I have an optional variable in the outer >> scope, it would remain optional in the inner scope, but the way the draft is >> worded, it might seem like it would add an implicit guard statement in that >> situation. i.e: >> >> var opt: Bool? >> var closure = ?{ >> if opt {} >> } >> >> => >> >> var opt: Bool? >> var closure = { >> guard let opt = opt else { return } >> if opt {} >> } >> >> What are your thoughts on this? > > This is a great question! > > In this example guarded closures make no difference at all because `Bool?` is > a value type so it is not captured by reference. > > Indeed, using Bool here was a bad choice for my example. > > > If it was an optional reference type the guard would fire as soon as the > value was `nil` which would be immediately if the value was already `nil` > when the closure was created. This is the same behavior you would get today > by writing it out manually. > > > I.e unless otherwise overridden with a [weak opt] or similar statement, this > ?{} syntax would also enforce non-nil status of any passed in reference > types. > > This could by itself be a very useful shortcut, but should probably be called > out explicitly in the proposal just to remove any possible confusion of > intent. As per my original question, it's most certainly obvious how this > would be handled. I'm also not sure if this is usually the most desirable > outcome. > > I think it would be more logical as a developer if your optionals remain > optional within the block, but with the difference that they aren't strongly > captured, and as such might become nil by the time the block executes, even > if they weren't at the time of creation. Removing the optionality might force > a lot of [weak param] statements that otherwise wouldn't be needed.
The intent is to make this behave exactly as if you had written it out manually and had guarded all captured references. I think it works when it changes the default. It would be confusing to add special cases for things that are already optional. If you don’t want guarded behavior you’ll just need to use the capture list as you showed. > > > >> >> David >> >> >> On Wed, Feb 22, 2017 at 1:40 PM, Matthew Johnson <matt...@anandabits.com >> <mailto:matt...@anandabits.com>> wrote: >> >>> On Feb 22, 2017, at 3:36 PM, David Hedbor via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> I did read it, but I think I skimmed it a bit too fast. You're correct in >>> that it essentially solves the same problem using a different syntax (more >>> compact at that). I think when I initially read it, I parsed it as the >>> method would return at any point if the objects were freed (mid-execution >>> of the closure). Re-reading it, I see that the proposal is in fact >>> identical in functionality to mine, just with a different syntax. >>> >>> Given that your proposal still allows for overriding the behavior on an >>> individual basis, the same thing can be accomplished. I'll put my support >>> behind your draft, rather than expending more time with mine. :) >> >> Thanks David, glad to hear it! >> >>> >>> Cheers, >>> >>> David >>> >>> >>> On Wed, Feb 22, 2017 at 12:57 PM, Matthew Johnson <matt...@anandabits.com >>> <mailto:matt...@anandabits.com>> wrote: >>> Hi David, >>> >>> I just shared a draft proposal to introduce guarded closures last week: >>> 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>. >>> I think you would find it very interesting. >>> >>> I considered including a new capture list specifier `guard` in this >>> proposal but decided against it. Guarded behavior requires prefixing the >>> contents of the closure with a guard clause that returns immediately if the >>> guard is tripped. This is a property of the closure as a whole, not of an >>> individual capture. For that reason, I decided that allowing a `guard` >>> specifier for an individual capture would be inappropriate. >>> >>> Instead, a guarded closure has a guarded by default capture behavior which >>> can be overridden with `weak`, `unowned` or `strong` in the capture list. >>> The thread on this proposal was relatively brief. I plan to open a PR soon >>> after making a few minor modifications. >>> >>> Matthew >>> >>>> On Feb 22, 2017, at 2:48 PM, David Hedbor via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>> Hello, >>>> >>>> (apologies if this got sent twice - gmail and Apple mail seems to confused >>>> as to what account the first mail was sent from) >>>> >>>> I’m new to this mailing list, but have read some archived messages, and >>>> felt that this would be a reasonable subject to discuss. It’s somewhat >>>> related to the recent posts about @selfsafae/@guarded but distinctly >>>> different regardless. >>>> >>>> >>>> Problem: >>>> >>>> It’s often desirable not to capture self in closures, but the syntax for >>>> doing so adds significant boilerplate code for [weak self] or us unsafe >>>> when used with [unowned self]. Typically you’d do something like this: >>>> >>>> { [weak self] in self?.execute() } >>>> >>>> This is simple enough but often doesn’t work: >>>> >>>> { [weak self] in self?.boolean = self?.calculateBoolean() ] >>>> >>>> This fails because boolean is not an optional. This in turn leads to code >>>> like this: >>>> >>>> { [weak self] in >>>> guard let strongSelf = self else { return } >>>> strongSelf.boolean = self.calculateBoolean() } >>>> >>>> And this is the boilerplate code. My suggestion is to add a syntax that >>>> works the same as the third syntax, yet doesn’t require the boilerplate >>>> code. >>>> >>>> >>>> Solution: >>>> >>>> Instead of using unowned or weak, let’s use guard/guarded syntax: >>>> >>>> >>>> { [guard self] in >>>> self.isExecuted = self.onlyIfWeakSelfWasCaptured() >>>> } >>>> >>>> In essence, guarded self is equivalent to a weak self, that’s captured >>>> when the closure is executed. If it was already released at that point, >>>> the closure is simply not executed. It’s equivalent to: >>>> >>>> { [weak self] in >>>> guard let strongSelf = self else { return } >>>> strongSelf.isExecuted = strongSelf.onlyIfWeakSelfWasCaptured() >>>> } >>>> >>>> Except with a lot less boilerplate code, while not losing any clarify in >>>> what it does. >>>> >>>> Impact / compatibility: >>>> >>>> This is simply additive syntax, and wouldn’t affect any existing code. >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <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 >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution