[swift-evolution] An upcoming proposal for simplifying leak free, safe closures.
admin at wheerd.de
admin at wheerd.de
Tue Jun 28 07:53:08 CDT 2016
Am 27.06.2016 20:55, schrieb Christopher Kornher:
>> On Jun 27, 2016, at 2:45 AM, Manuel Krebber via swift-evolution
>> <swift-evolution at swift.org> wrote:
>>
>> On 06/26/2016 09:10 PM, Christopher Kornher via swift-evolution wrote:
>>> The core proposal:
>>> ——————
>>>
>>> Closures capturing object references should automatically capture all
>>> object references as weak.
>> In my code, most closures are used in a functional programming
>> capacity,
>> e.g. with map(), reduce, etc. Hence, most closures are non-escaping
>> and
>> local, where strong capture is the desired way. Otherwise I would have
>> to litter everything with optional unwrapping or add the explicit
>> capture definition which would both make the code less readable in my
>> opinion.
>
> I thought about this some more and it makes sense to treat
> non-escaping closures are they are treated now. This might increase
> the burden on the compiler especially because these closures may not
> be declared inline. This would be far more straightforward than having
> to worry about changes to object existence within one or more
> invocations of a @nonescaping closure, especially in multi-threaded
> code.
>
> I do not think that this would be a significant change for developers
> in practice. Any developer who would try to rely upon object
> references changing within the application of a @nonescaping closure
> would probably have read the manual very carefully :)
>
>
I am unsure whether treating closures differently depending on a
@nonescaping attribute on a function is a good idea.
The problem is that, theoretically, the closure might be stored in a
variable or used with different functions. Then how do you decide
whether the default is strong or weak capture?
Example:
func f1(_ f : (Int) -> Int) {
...
}
func f2(_ f : @noescape (Int) -> Int) {
...
}
let foo = Foo()
let f : (Int) -> Int = {
return foo.x
}
f1(f)
f2(f)
In addition different default capture behaviour dependant on context
could be confusing for developers I think.
>>> 1) Closures with object references could be simplified further by
>>> implicitly including ‘let’ guards for all object references:
>> This sounds good for closures without return value, but how would you
>> handle closures with non-optional non-void return values?
>
> Good point.
>
> 1) The simplest solution would be to have these closures require
> capture lists to some or all object references. Given the prevalence
> of the weak/strong dance, calling these out in some way probably
> should be done anyway.
>
> 2) Another option would be to eliminate the implicit nil check guards,
> making all object references optional. The compiler would force these
> to be unwrapped, so users would be guided to do the right thing.
>
> 3) Just always weakly capturing all object references would treat all
> closures uniformly.
>
I think I favour 2) out of these, even though it still means the code
will potentially be littered with ?. or let guards...
Kind regards, Manuel
More information about the swift-evolution
mailing list