[swift-evolution] Guaranteed closure execution

T.J. Usiyan griotspeak at gmail.com
Sat Jan 30 14:57:48 CST 2016


+1

I've wanted the ability require that a closure be called for a little while
now. Clean up code is an example of when this can be useful.

On Sat, Jan 30, 2016 at 9:54 PM, Félix Cloutier <swift-evolution at swift.org>
wrote:

> Can the compiler even enforce it? If the closure escapes, it necessarily
> means that you assigned it elsewhere. How do you enforce that you never
> call this reference more than once?
>
> If the compiler can't take advantage of it and can't enforce it either, I
> would rather not have it at all.
>
> I would also think that for a lot of APIs with an escaping closure, it
> could be more useful to say that it will be called "at most once" than
> "exactly once". Additionally, if completion blocks are the main client of
> the feature, I would avoid giving it too much effort before we figure out
> the favored concurrency model.
>
> @noescape(once) really looks like a special case to me, because it's
> enforceable, useful to the compiler and useful to the user.
>
> Félix
>
> Le 30 janv. 2016 à 15:07:11, Matthew Johnson <matthew at anandabits.com> a
> écrit :
>
>
> On Jan 30, 2016, at 1:56 PM, Félix Cloutier via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I agree that many closures are expected to be executed only once, but it
> seems to me that it's only useful to the compiler if it's also marked
> @noescape. A completion handler marked "once" without "noescape" doesn't
> allow the compiler to determine that a variable will have been initialized
> after the call that takes the closure.
>
> So in these other cases, it only serves as documentation. I'm not very
> enthusiastic about attributes that only serve as documentation because
> there is an infinity of attributes that can be added to the language for
> documentation purposes.
>
>
> It also serves as a guarantee that the closure is executed exactly once.
> Even if the compiler can’t use it for optimization the guarantee could be
> useful.
>
>
> There are other places than `dispatch_sync` where you may want a
> `@noescape(once)` attribute. Any function that executes a closure while
> providing some sort of guarantee/RAII-like handle can benefit from it. Most
> of the functions starting with `with` in the standard library could benefit
> from it: withExtendedLifetime, withUnsafePointer and friends, withVaList.
> String's `withCString` and `withMutableCharacters` could benefit from it
> too. Someone who writes a `withLock(lock) { closure }` function would be
> happy to have it too.
>
> Félix
>
> Le 30 janv. 2016 à 07:11:23, Rod Brown <rodney.brown6 at icloud.com> a écrit
> :
>
> I'm very supportive of this type of proposal.
>
> I do agree with Brent though that @noescape and 'once' is somewhat
> orthogonal.
>
> There are a lot of places where you want to be clear that the block will
> be called but no more than once. For example, the NSURLSession callback
> blocks you would expect never to be called multiple times. Completion
> handlers are almost always used only once. I don't think this case, which
> is extremely common, can be overlooked.
>
> On the other hand, I suspect the majority of places you use closures with
> @noescape, it seems more likely you'd *want *it used multiple times, like
> a search, filter, find etc of multiple items in a collection or group,
> otherwise you'd generally just put the closured activity before or after.
> The only areas where I would expect to see such closures of @noescape and
> 'once' would be dispatch_sync, or somewhere where you want to invoke custom
> code in the middle of a complex operation of a method.
>
> It seems to me that separating them, but allowing them to be used
> together, makes more sense.
>
> Rod
>
>
> On 30 Jan 2016, at 5:05 AM, Félix Cloutier via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I don't have much to add but I also think that it would be nice to have.
>
> Félix
>
> Le 29 janv. 2016 à 12:38:01, Chris Lattner via swift-evolution <
> swift-evolution at swift.org> a écrit :
>
> On Jan 29, 2016, at 12:23 AM, Jacob Bandes-Storch via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I've wanted something like this as well. I think it would be harder than
> it seems, because "x = 1" might need to perform initialization, or
> assignment, depending how it's used.
>
> It could make sense to have something like
> "@noescape(executed_exactly_once)" but this might be so limited it's not
> worth it. And I'm not sure how it should interact with throws.
>
>
> I think that something like this is implementable, and making it a
> modifier to @noescape is sensible.
>
> The semantics we could support is that the function is guaranteed to call
> the closure exactly once on any path that could lead to a return or throw.
>
> This approach allows you to pass the closure down the stack, and composes
> with error handling.  It is obviously limited what you can do with the
> closure, but that is necessary to validate correctness.
>
> -Chris
>
>
>
>
> Jacob
>
> On Thu, Jan 28, 2016 at 11:38 PM, Gwendal Roué <swift-evolution at swift.org>
>  wrote:
>
>> Hello,
>>
>> I’d like to discuss the opportunity to let functions declare that a
>> closure argument is guaranteed to have been executed when the function has
>> returned.
>>
>> For example:
>>
>> func f(@noescape(executed) closure: () -> ()) {
>>     closure()
>> }
>>
>> The expected advantage is that the compiler would know that a variable
>> set inside the closure is guaranteed to be initialized, and that it can be
>> used after the execution of the function, as below:
>>
>> let x: Int  // Not initialized
>> f { x = 1 }
>> print(x)    // Guaranteed to be initialized
>>
>> Today developers have to write pessimistic code like below:
>>
>> var x: Int = 0 // `var` declaration, with some irrelevant value
>> f { x = 1 }
>> print(x)
>>
>> As for a real world usage, I’d like to access a database in a safe
>> (queued) way, and fetch values out of it:
>>
>> let items: [Item]
>> let users: [User]
>> dbQueue.inDatabase { db in
>>     items = Item.all().fetchAll(db)
>>     users = Item.all().fetchAll(db)
>> }
>>
>> Gwendal Roué
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> swift-evolution mailing list
> 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/20160130/8f88dd07/attachment.html>


More information about the swift-evolution mailing list