-1
I support improvements in this area but I do not think that adding guarded
closures will fix the case.
It raises multiple concerns:
- prepending ? to the closure declaration is as forgettable as `[weak self]`
- reactive programming often assumes chaining of operations. How guarded
closures affect next operations in the chain?
- the closure must exist until either the control deallocates (source of
actions) or self deallocates (destination of actions). Guarded closure will not
provide an expected behavior
- managing lifecycle of nested guarded closures could be complex to understand
and implement into the language
- why would you consider using @escaping instead of @guarded?
I personally prefer doing something like this:
```swift
self.button.onAction(forEvents: [.touchUpInside], context: self) { (self,
sender, event) in
self.performSearch(query: self.searchField.text)
}
```
or
```swift
self.button.actions(forEvents: [.touchUpInside])
.debounce(interval: 3.0)
.map(context: self) { (self, _) in
return self.searchField.text
}
.distinct()
.onUpdate(context: self) { (self, searchQuery) in
self.performSearch(query: searchQuery)
}
```
This code neither requires an addition of language features nor contains retain
cycles. All closures will be released as soon as source or destination
deallocates.
> On Feb 22, 2017, at 22:57, Matthew Johnson via swift-evolution
> <[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
>
> <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] <mailto:[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] <mailto:[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