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@anandabits.com> a
écrit :
On Jan 30, 2016, at 1:56 PM, Félix Cloutier via swift-evolution < > swift-evolution@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@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@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@swift.org> a écrit :
On Jan 29, 2016, at 12:23 AM, Jacob Bandes-Storch via swift-evolution < > swift-evolution@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@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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution