[swift-evolution] [Draft] Guarded closures and `@guarded` arguments

Matthew Johnson matthew at anandabits.com
Wed Feb 22 15:39:59 CST 2017


> On Feb 22, 2017, at 3:14 PM, David Hart <david at hartbit.com> wrote:
> 
> Hi Matthew,
> 
> Finally found time to read the proposal. Much better than the previous iterration. I’m not a huge fan of the proposed syntax either but don’t have the energy for bike shedding :)

The requirements I have for the syntax are:
* it must work with both bound instance method references and closures
* it must be reasonably concise
* it must have some relationship to `@guarded` arguments

The last requirement is the reason I opted for a prefix sigil.  The closest parallel we have is `inout` and that uses a prefix sigil.  As soon as you decide to use a prefix sigil `?` is the obvious choice for this behavior.

I am certainly open to hearing alternatives, but they should address each of the three requirements listed above.  (I mention this mostly in case anyone else reading does have energy to bikeshed on this).

> 
> As a side note, I’d like to say that I would not use this very often. I much more often use unowned capture variables when its clear that the closure can’t outlive the captured variable. For example, my code often looks like this:
> 
> class MyViewController : UIViewController {
>     var button: ActionButton!
>     
>     override func viewDidLoad() {
>         super.viewDidLoad()
>         
>         button.addAction { [unowned self] in
>             print("self: \(self)")
>         }
>     }
> }

Hi David.  Thanks for replying!  I’m glad you like this approach better.  I think I have finally hit on an elegant mechanism for providing safer default semantics for callbacks arguments along with a much more concise syntax for a very widespread pattern.  I’ve been thinking about this problem ever since Swift first came out and am pretty pleased with this approach.

That’s certainly a reasonable way for somebody who really understands what they’re doing to write code.  There is an overhead in the weak references and the guards that isn’t necessary in this case.  The good news is that this would still be valid code within a guarded closure because the new proposal allows you to override the guarded behavior using the capture list.

> 
>> On 20 Feb 2017, at 18:01, Matthew Johnson via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> 
>>> On Feb 20, 2017, at 8:33 AM, Florent Bruneau <florent.bruneau at intersec.com <mailto:florent.bruneau at intersec.com>> wrote:
>>> 
>>> 
>>> 
>>>> Le 20 févr. 2017 à 06:35, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> a écrit :
>>>> 
>>>>> On Feb 19, 2017, at 2:57 PM, Matthew Johnson via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> 
>>>>> A guarded closure may be created by prefixing a bound instance method reference with the `?` sigil:
>>>>> 
>>>>> ```swift
>>>>> let guarded = ?myObject.myMethod
>>>>> 
>>>>> // desugars to:
>>>>> let guarded = { [weak myObject] in
>>>>> guard let myObejct = myObject else {
>>>>> return
>>>>> }
>>>>> myObject.myMethod()
>>>>> }
>>>>> ```
>>>> 
>>>> I like this in principle, but I don't like the syntax. The `?` is cryptic and looks pretty strange in prefix position. I think what I'd like to see is:
>>>> 
>>>> 	let guarded = weak myObject.myMethod
>>> 
>>> I like the idea of weak closures even if this may conflict with the fact closures are already internally refcounted object. While we cannot have weak references to closure in the language, using `weak` might be misleading in some ways.
>>> 
>>> In term of syntax, the `weak` keyword looks nice (much better than the '?' and @guarded once). The weak could be used on both sides.
>>> 
>>> ```swift
>>> addAction(action: weak Action)
>>> addAction(action: weak myAction)
>>> ```
>>> 
>>> However, I think this might still look weird with inlined closures, in particular in case you use the suffix syntax for closures:
>>> 
>>> ```swift
>>> addAction() weak {
>>>   /* */
>>> }
>>> ```
>> 
>> 
>> We wouldn’t want to use `weak` if this has the guarded behavior I proposed.  We could use `guarded` though.
>> 
>> There are a couple of important things enabled by having the language implement the guarded behavior.  
>> 
>> First, the implementation could release the entire closure context as soon as one of the guarded captures is released.  This is not possible if users write the code out manually.  Second, in the future directions I discuss allowing libraries to detect that the guard has been triggered and the closure has become a no-op.  This is also not possible when users write the guard out manually and would be quite desirable for libraries that want to discard their reference to the closure after it becomes a no-op.
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto: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/20170222/ec2f0609/attachment.html>


More information about the swift-evolution mailing list