On Wed, Feb 22, 2017 at 3:09 PM, Matthew Johnson <[email protected]> wrote:
> > On Feb 22, 2017, at 4:57 PM, David Hedbor <[email protected]> wrote: > > > > > On Wed, Feb 22, 2017 at 2:23 PM, Matthew Johnson <[email protected]> > wrote: > >> >> On Feb 22, 2017, at 4:06 PM, David Hedbor <[email protected]> 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. > Ok, I can buy that. Still feel like this should be explicitly called out. It's literally equivalent to [weak X] + guard let x = x { else return } for each and every captured reference, unless otherwise overridden in the capture list. > > > > >> >> >> David >> >> >> On Wed, Feb 22, 2017 at 1:40 PM, Matthew Johnson <[email protected]> >> wrote: >> >>> >>> On Feb 22, 2017, at 3:36 PM, David Hedbor via swift-evolution < >>> [email protected]> 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 < >>> [email protected]> 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. 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 < >>>> [email protected]> 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 >>>> [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
