Thanks for your input Michael,
You're right that argument modifiers should go before the argument, and type
qualifiers before the type:
func f(@once closure: @noescape () -> ())
Since @once actually implies @noescape (as described earlier in the thread), it
can be shortened to:
func f(@once closure: () -> ()) // implicit @noescape
> Or maybe it's just because I can't think of a realistic use case for using
> "@noescape(once)".
The use case is the following: @once closures let the compiler know that the
closure code is executed. It allows declaration of undefined `let` variables
that are initialized in the @once closure:
let x: Int
f { x = 1 }
// use x
Without @once, the developer has to work around:
var x: Int = 0 // two problems: `var` declaration, and dummy value
f { x = 1 }
// use x
If this proposal would be accepted, the next step would be to ask for
dispatch_sync functions et al. to use this qualifier (as well as other standard
functions like autoreleasepool, withUnsafeBufferPointer, etc.):
let x: Int
dispatch_sync(queue) {
x = 1
}
And now high-level objects that use internal queues are easier to use:
let items: [Item]
let users: [User]
dbQueue.inDatabase { db in
items = Item.fetchAll(db)
users = User.fetchAll(db)
}
This pattern would greatly improve many libraries, and my own
http://github.com/groue/GRDB.swift in particular.
Gwendal Roué
> Le 23 avr. 2016 à 14:16, Michael Peternell <[email protected]> a écrit
> :
>
> Hi Gwendal,
>
>> Am 23.04.2016 um 12:18 schrieb Gwendal Roué via swift-evolution
>> <[email protected]>:
>>
>> Hello Andrew,
>>
>> I'm rather embarrassed: the initial design of this proposal was based on a
>> modifier of @noescape:
>>
>> func f(@noescape(once) closure: () -> ()) { … }
>>
>> But since the 0049 proposal has been accepted
>> (https://github.com/apple/swift-evolution/blob/master/proposals/0049-noescape-autoclosure-type-attrs.md),
>> @noescape is no longer an argument qualifier, but a type attribute.
>
> maybe I cannot give competent advice from the language designers perspective,
> but I can speak as a language user.
>
> I think it is more intuitive to have the name of the argument first:
> "ARGUMENT-NAME: NOESCAPE AUTOCLOSURE TYPE FOOBAR-QUALIFIER...,
> NEXT-ARGUMENT-NAME..." and not "SOME-MODIFIERS-FIRST ARGUMENT-NAME:
> SOME-MODIFIERS-LAST". I think the old behavior reminded me too much of C,
> where the argument name is at some arbitrary place, surrounded by type names,
> parens, and whatnot; "void foo(int __cdecl (*bar)(int foobar, void
> *context))" where "bar" is the argument name, the first "int" is the return
> type of the "bar" function, "int" and "void*" are the two argument types, and
> "__cdecl" is the calling convention of the "bar" function.
>
> And about @noescape(once)... Would it not work anymore? I know it's not part
> of the current SE-0049 proposal, but I can't see why it couldn't be expanded
> to include `once`. Or maybe it's just because I can't think of a realistic
> use case for using "@noescape(once)".
>
>> The `once` discussed here can not be part of the type: if noescape can
>> understandably be part of the type, the fact that a function guarantees it
>> will call a closure once is a quality of that function, not of the closure.
>
> Yes it is a quality of the function and not of the type. But why not just
> leave it at that place and just call it "argument qualifier"? Or maybe the
> general layout changed? In Swift 2 it was "ARGUMENT_QUALIFIERS ARGUMENT_NAME:
> TYPE_ATTRIBUTES TYPE", and in Swift 3 it is "ARGUMENT_NAME:
> ARGUMENT_QUALIFIERS TYPE_ATTRIBUTES TYPE"?
>
>> So the proposed @noescape(once) syntax is now confusing as it would mix a
>> type attribute and a argument qualifier.
>>
>> I don't quite know how to escape this:
>>
>> // two @ signs
>> func f(@noescape @once closure: () -> ()) { … }
>>
>> // Implies @noescape
>> func f(@once closure: () -> ()) { … }
>
> How about
>
> func f(closure: @noescape(once) () -> ()) { ... }
>
> -Michael
>
>>
>> I'd like advice from competent people before I would attempt a rewrite of
>> the proposal.
>>
>> Gwendal Roué
>>
>>> Le 10 avr. 2016 à 23:26, Andrew Bennett <[email protected]> a écrit :
>>>
>>> Sorry I missed that scrolling back through the history, that proposal looks
>>> great. It doesn't look like it has been submitted as a pull request to
>>> swift-evolution yet though.
>>>
>>> On Sunday, 10 April 2016, Gwendal Roué <[email protected]> wrote:
>>> Felix Cloutier already wrote one:
>>> https://github.com/zneak/swift-evolution/blob/master/proposals/00xx-noescape-once.md
>>>
>>> Do you think it needs to be rewritten?
>>>
>>> Gwendal Roué
>>>
>>>> Le 10 avr. 2016 à 14:56, Andrew Bennett <[email protected]> a écrit :
>>>>
>>>> Hi, not beyond this thread that I have seen. I think it's worth you
>>>> summarizing this thread in a formal proposal and putting it up for
>>>> discussion or submitting it as a PR :)
>>>>
>>>> On Sunday, 10 April 2016, Gwendal Roué <[email protected]> wrote:
>>>> Hello all,
>>>>
>>>> I was wondering if this topic had evolved in anyway since its original
>>>> introduction.
>>>>
>>>> @noescape(once) would still be a useful addition to the language!
>>>>
>>>> Gwendal Roué
>>>>
>>>>
>>>>
>>>>> Le 3 févr. 2016 à 22:21, Félix Cloutier via swift-evolution
>>>>> <[email protected]> a écrit :
>>>>>
>>>>> I updated the proposal to address some concerns. It can be found at:
>>>>> https://github.com/zneak/swift-evolution/blob/master/proposals/00xx-noescape-once.md
>>>>>
>>>>> Things that changed:
>>>>>
>>>>> • It now says that the closure must be called on code paths where the
>>>>> function throws;
>>>>> • you can have multiple @noescape(once) parameters but they can't make
>>>>> assumptions from one another.
>>>>>
>>>>> I'm not 100% convinced that forcing a call on code paths that throw is
>>>>> always desirable. I've changed it because Chris's support probably means
>>>>> that the feature has better chances of making it, but I'm not convinced
>>>>> yet. If throwing allows me to return without calling the closure, I can
>>>>> write this:
>>>>>
>>>>> do {
>>>>> let foo: Int
>>>>> try withLock(someLock, timeout: 0.5) {
>>>>> foo = sharedThing.foo
>>>>> }
>>>>> } catch {
>>>>> print("couldn't acquire lock fast enough")
>>>>> }
>>>>>
>>>>> which would be kind of messy if instead, the closure needed a parameter
>>>>> to tell whether the lock was acquired or not when it runs.
>>>>>
>>>>> Félix
>>>>>
>>>>> _______________________________________________
>>>>> 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
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution