Re: [swift-evolution] async void

2017-11-13 Thread Adam Kemp via swift-evolution


> On Nov 12, 2017, at 1:47 PM, David Waite  wrote:
> 
> From what I understand, the C# and Swift designs are different:
> 
> - C# async functions immediately return a task which can be enqueued to 
> complete the work (including selecting which queue for UI cases, etc). Tasks 
> have callback behavior attached to them.

Tasks in C# don’t represent something that can be enqueued. They represent work 
that is already taking place asynchronously, and the Task object can be used to 
install a callback or to fetch the result synchronously (ideally only after the 
work is already completed). You can’t use a Task to control which queue the 
work runs on (there may be no queue at all). You can use it to configure how an 
await will resume (essentially, which queue should be used), but that’s 
different from configuring on which queue the work will run.

> 
> - Swift async functions immediately enqueue to do work along with a callback 
> function to be executed once work finishes. There is no first-class 
> representation of a Future or the like, at least by default (a callback 
> function could be promoted to a future). There is no support for selecting 
> which queue work or the callback runs on (although your callback could 
> immediately enqueue work on the appropriate thread, but this does increase 
> latency in busy systems)
> 
> Assuming I got the above all correct there is no async Task vs async Void in 
> swift, because a function which dispatches work to a queue without taking a 
> callback just returns void. Those functions aren’t “async” at all, you can 
> call them normally to dispatch work just as easily as you could call them 
> within an async block, and they would have the same behavior. They also can’t 
> be “awaited”, because there is no callback mechanism to tell when the work 
> completes.

The async keyword isn’t used to denote a function that does work 
asynchronously. It’s a bit of a misnomer in that way. What it actually denotes 
is “this function can use the await keyword”. That’s why there is a concept of 
“async void” in C#: because it’s possible to use the await keyword in a 
function that can’t itself be awaited. It exists for the same reason that 
beginAsync exists in the proposal. My argument is just that it is easier to use 
the feature if you just allow non-awaitable functions to use await and have 
some kind of syntax for that.

> 
> Thats not to say I wouldn’t prefer the Task-type design, but it isn’t how 
> most of the legacy asynchronous code is written to work (and would have some 
> issues with GCD, since you can’t discover your current queue in order to 
> enqueue more work there by default)

This has been discussed before. Getting the current queue is discouraged for 
client code because it’s usually an invalid thing to ask for (there isn’t just 
a single current queue), but there’s nothing wrong with the runtime or standard 
library using that to do meaningful things. Getting the current queue to resume 
an async task is a reasonable thing to do, and it could be built in. Look for 
the earlier emails from Pierre Habouzit about this topic for more information.

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] async void

2017-11-13 Thread Adam Kemp via swift-evolution
However, equally important to the case I was making earlier is that you should 
be able to call an “async Never” function as if it were a non-async Void 
function. This is especially important for cases where you want to pass a 
callback to something (like an event handler), and you want the callback to be 
able to use await. So as long as that still works I could live with "async 
Never”.

> On Nov 13, 2017, at 9:49 AM, Adam Kemp  wrote:
> 
> I kind of like that idea. I’d rather have a Task/Future/Promise/whatever, but 
> if that’s not going to happen then Void vs. Never seems like a reasonable way 
> of distinguishing these two cases.
> 
>> On Nov 12, 2017, at 9:55 AM, Xiaodi Wu > > wrote:
>> 
>> Sorry, I'm just getting into this conversation late and am by no means 
>> experienced in the area, but why can't the one where you *don't* want the 
>> caller to wait for the result be spelled `async -> Never`? Theoretically, 
>> `async -> Void` means you're awaiting a result with only one possible value, 
>> but if you're not waiting at all, then there is truly no result, yes?
>> 
>> 
>> On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> Sorry, I had got some confusion. Please let me retry to explain.
>> 
>> As you said, C# provides three kinds of async functions: `async Void`,
>> `async Task` and `async Task`. All of them are necessary and
>> Swift should provide same functionalities.
>> 
>> When we think about `async/await` in Swift, because we have already
>> had `throws/try`, it is desired that `async/await` in Swift is
>> consistent with `throws/try`. So it is better to have `async/await`
>> without introducing a type like `Task` (or `Promise`).
>> 
>> Even if we employ `async/await` without `Task`, Swift has to provides
>> functionalities to implement "three kinds of async functions" in C#.
>> However if `async -> Void` in Swift works similarly to `async Void` in
>> C#, how can we express ones like `async Task` in C#? I think there are
>> two possibilities:
>> 
>> 1. Calling `async -> Void` functions without `await` in Swift works
>> like `async Void` in C# and calling them *with* `await` works like
>> `async Task` in C#.
>> 2. Calling `async -> Void` functions without `await` in Swift works
>> like `async Void` in C# and never support something like `async Task`
>> in C#.
>> 
>> I think 2 is impermissible. For example, handling completion events of
>> asynchronous operations without result values needs something like
>> `async Task` in C#. However, with 1, we lose the benefit of static
>> checks by the compiler. Because both of `fooAsync()` without `await`
>> and `await fooAsync()` are allowed, even if we want it to work like
>> `async Task` in C# and forget to mark `await`, the compiler tell us
>> nothing and it works like `async Void` in C#. It causes unexpected
>> behaviors. It is hard to fix such kinds of bugs. So I think
>> introducing `beginAsync` is better.
>> 
>> --
>> Yuta
>> 
>> 
>> 2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution
>> mailto:swift-evolution@swift.org>>:
>> > 2017-11-12 2:57 GMT+09:00 Adam Kemp > > >:
>> >>
>> >>
>> >>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa > >>> > wrote:
>> >>>
>> >>> If you replace `async` with `throws`, you can get answers.
>> >>>
>> >>>
>>  Can you declare an async closure variable?
>> >>>
>> >>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
>> >>>
>> >>>
>>  Can a non-async closure be passed to a function expecting a async 
>>  closure?
>> >>>
>> >>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
>> >>> closure `() throws -> Void`.
>> >>>
>> >>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
>> >>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
>> >>> same way.
>> >>>
>> >>> To treat an async function as a sync function is legal. It is similar
>> >>> to make a `Promise` by `Promise(value)` which is completed
>> >>> immediately.
>> >>>
>> >>>
>>  Can an async closure be passed to a function expecting a non-async 
>>  closure?
>> >>>
>> >>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
>> >>> passing `() throws -> Void` to a function expecting `() -> Void` is
>> >>> not allowed.
>> >>
>> >> But why not? Just asserting that it must work the same as throws
>> >> is not a convincing argument. You have to justify why it must work
>> >> that way. I think there is good reason to allow it, which I have 
>> >> described.
>> >> What reason is there to disallow it?
>> >
>> > `() async -> Void` needs to be called with `await` because it prevents
>> > us from forgetting handling asynchronous operations.
>> >
>> > If we use callbacks to handle asynchronous operations, it is shown to
>> > us by a compiler as a compilation error.
>> >
>> > ```
>> > func fooAsync(_ handler: () -> Void) -

Re: [swift-evolution] async void

2017-11-13 Thread Adam Kemp via swift-evolution
I kind of like that idea. I’d rather have a Task/Future/Promise/whatever, but 
if that’s not going to happen then Void vs. Never seems like a reasonable way 
of distinguishing these two cases.

> On Nov 12, 2017, at 9:55 AM, Xiaodi Wu  wrote:
> 
> Sorry, I'm just getting into this conversation late and am by no means 
> experienced in the area, but why can't the one where you *don't* want the 
> caller to wait for the result be spelled `async -> Never`? Theoretically, 
> `async -> Void` means you're awaiting a result with only one possible value, 
> but if you're not waiting at all, then there is truly no result, yes?
> 
> 
> On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> Sorry, I had got some confusion. Please let me retry to explain.
> 
> As you said, C# provides three kinds of async functions: `async Void`,
> `async Task` and `async Task`. All of them are necessary and
> Swift should provide same functionalities.
> 
> When we think about `async/await` in Swift, because we have already
> had `throws/try`, it is desired that `async/await` in Swift is
> consistent with `throws/try`. So it is better to have `async/await`
> without introducing a type like `Task` (or `Promise`).
> 
> Even if we employ `async/await` without `Task`, Swift has to provides
> functionalities to implement "three kinds of async functions" in C#.
> However if `async -> Void` in Swift works similarly to `async Void` in
> C#, how can we express ones like `async Task` in C#? I think there are
> two possibilities:
> 
> 1. Calling `async -> Void` functions without `await` in Swift works
> like `async Void` in C# and calling them *with* `await` works like
> `async Task` in C#.
> 2. Calling `async -> Void` functions without `await` in Swift works
> like `async Void` in C# and never support something like `async Task`
> in C#.
> 
> I think 2 is impermissible. For example, handling completion events of
> asynchronous operations without result values needs something like
> `async Task` in C#. However, with 1, we lose the benefit of static
> checks by the compiler. Because both of `fooAsync()` without `await`
> and `await fooAsync()` are allowed, even if we want it to work like
> `async Task` in C# and forget to mark `await`, the compiler tell us
> nothing and it works like `async Void` in C#. It causes unexpected
> behaviors. It is hard to fix such kinds of bugs. So I think
> introducing `beginAsync` is better.
> 
> --
> Yuta
> 
> 
> 2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution
> mailto:swift-evolution@swift.org>>:
> > 2017-11-12 2:57 GMT+09:00 Adam Kemp  > >:
> >>
> >>
> >>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa  >>> > wrote:
> >>>
> >>> If you replace `async` with `throws`, you can get answers.
> >>>
> >>>
>  Can you declare an async closure variable?
> >>>
> >>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
> >>>
> >>>
>  Can a non-async closure be passed to a function expecting a async 
>  closure?
> >>>
> >>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
> >>> closure `() throws -> Void`.
> >>>
> >>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
> >>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
> >>> same way.
> >>>
> >>> To treat an async function as a sync function is legal. It is similar
> >>> to make a `Promise` by `Promise(value)` which is completed
> >>> immediately.
> >>>
> >>>
>  Can an async closure be passed to a function expecting a non-async 
>  closure?
> >>>
> >>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
> >>> passing `() throws -> Void` to a function expecting `() -> Void` is
> >>> not allowed.
> >>
> >> But why not? Just asserting that it must work the same as throws
> >> is not a convincing argument. You have to justify why it must work
> >> that way. I think there is good reason to allow it, which I have described.
> >> What reason is there to disallow it?
> >
> > `() async -> Void` needs to be called with `await` because it prevents
> > us from forgetting handling asynchronous operations.
> >
> > If we use callbacks to handle asynchronous operations, it is shown to
> > us by a compiler as a compilation error.
> >
> > ```
> > func fooAsync(_ handler: () -> Void) -> Void { ... }
> >
> > fooAsync() // compilation error
> >
> > fooAsync {
> >   // handles a completion event here
> > }
> > ```
> >
> > With proposed `async/await`, it is realized similarly like below.
> >
> > ```
> > func fooAsync() async -> Void { ... }
> >
> > fooAsync() // compilation error
> >
> > await fooAsync()
> > // handles a completion event here
> > ```
> >
> > However, if async void functions work like `beginAsync`, we can easily
> > forget it and it can cause unexpected behaviors.
> >
> > ```
> > func fooAsync() async -> Void { ... }
> >
> > fooAsync() // OK
> > // hard t

Re: [swift-evolution] async void

2017-11-12 Thread David Waite via swift-evolution
>From what I understand, the C# and Swift designs are different:

- C# async functions immediately return a task which can be enqueued to 
complete the work (including selecting which queue for UI cases, etc). Tasks 
have callback behavior attached to them.

- Swift async functions immediately enqueue to do work along with a callback 
function to be executed once work finishes. There is no first-class 
representation of a Future or the like, at least by default (a callback 
function could be promoted to a future). There is no support for selecting 
which queue work or the callback runs on (although your callback could 
immediately enqueue work on the appropriate thread, but this does increase 
latency in busy systems)

Assuming I got the above all correct there is no async Task vs async Void in 
swift, because a function which dispatches work to a queue without taking a 
callback just returns void. Those functions aren’t “async” at all, you can call 
them normally to dispatch work just as easily as you could call them within an 
async block, and they would have the same behavior. They also can’t be 
“awaited”, because there is no callback mechanism to tell when the work 
completes.

Thats not to say I wouldn’t prefer the Task-type design, but it isn’t how most 
of the legacy asynchronous code is written to work (and would have some issues 
with GCD, since you can’t discover your current queue in order to enqueue more 
work there by default)

// Function which asynchronously dispatches work, without triggering any 
callback. If it throws, the error represents a synchronous issue (e.g. bad 
parameters or state)

func doWorkBlindly();

// Function which asynchronously dispatches work, returning a callback without 
data but possibly indicating an error
func doWorkExceptionally() async -> Void;

// Function which asynchronously dispatches work ,returning data and possibly 
an error
func doValuableWork() async -> Data;

// works fine
doWorkBlindly()
beginAsync {
// has the same behavior as above
doWorkBlindly()
do {
// can only be called within an async block
await doWorkExceptionally()
let result = await doValuableWork()
}
catch {
   fatalError()
}
}

-DW


> On Nov 12, 2017, at 10:56 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Sorry, I'm just getting into this conversation late and am by no means 
> experienced in the area, but why can't the one where you *don't* want the 
> caller to wait for the result be spelled `async -> Never`? Theoretically, 
> `async -> Void` means you're awaiting a result with only one possible value, 
> but if you're not waiting at all, then there is truly no result, yes?
> 
> 
> On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> Sorry, I had got some confusion. Please let me retry to explain.
> 
> As you said, C# provides three kinds of async functions: `async Void`,
> `async Task` and `async Task`. All of them are necessary and
> Swift should provide same functionalities.
> 
> When we think about `async/await` in Swift, because we have already
> had `throws/try`, it is desired that `async/await` in Swift is
> consistent with `throws/try`. So it is better to have `async/await`
> without introducing a type like `Task` (or `Promise`).
> 
> Even if we employ `async/await` without `Task`, Swift has to provides
> functionalities to implement "three kinds of async functions" in C#.
> However if `async -> Void` in Swift works similarly to `async Void` in
> C#, how can we express ones like `async Task` in C#? I think there are
> two possibilities:
> 
> 1. Calling `async -> Void` functions without `await` in Swift works
> like `async Void` in C# and calling them *with* `await` works like
> `async Task` in C#.
> 2. Calling `async -> Void` functions without `await` in Swift works
> like `async Void` in C# and never support something like `async Task`
> in C#.
> 
> I think 2 is impermissible. For example, handling completion events of
> asynchronous operations without result values needs something like
> `async Task` in C#. However, with 1, we lose the benefit of static
> checks by the compiler. Because both of `fooAsync()` without `await`
> and `await fooAsync()` are allowed, even if we want it to work like
> `async Task` in C# and forget to mark `await`, the compiler tell us
> nothing and it works like `async Void` in C#. It causes unexpected
> behaviors. It is hard to fix such kinds of bugs. So I think
> introducing `beginAsync` is better.
> 
> --
> Yuta
> 
> 
> 2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution
> mailto:swift-evolution@swift.org>>:
> > 2017-11-12 2:57 GMT+09:00 Adam Kemp  > >:
> >>
> >>
> >>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa  >>> > wrote:
> >>>
> >>> If you replace `async` with `throws`, you can get answers.
> >>>
> >>>
>  Can you declare an async closure variable?
> >>>
> >>

Re: [swift-evolution] async void

2017-11-12 Thread Xiaodi Wu via swift-evolution
Sorry, I'm just getting into this conversation late and am by no means
experienced in the area, but why can't the one where you *don't* want the
caller to wait for the result be spelled `async -> Never`? Theoretically,
`async -> Void` means you're awaiting a result with only one possible
value, but if you're not waiting at all, then there is truly no result, yes?


On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution <
swift-evolution@swift.org> wrote:

> Sorry, I had got some confusion. Please let me retry to explain.
>
> As you said, C# provides three kinds of async functions: `async Void`,
> `async Task` and `async Task`. All of them are necessary and
> Swift should provide same functionalities.
>
> When we think about `async/await` in Swift, because we have already
> had `throws/try`, it is desired that `async/await` in Swift is
> consistent with `throws/try`. So it is better to have `async/await`
> without introducing a type like `Task` (or `Promise`).
>
> Even if we employ `async/await` without `Task`, Swift has to provides
> functionalities to implement "three kinds of async functions" in C#.
> However if `async -> Void` in Swift works similarly to `async Void` in
> C#, how can we express ones like `async Task` in C#? I think there are
> two possibilities:
>
> 1. Calling `async -> Void` functions without `await` in Swift works
> like `async Void` in C# and calling them *with* `await` works like
> `async Task` in C#.
> 2. Calling `async -> Void` functions without `await` in Swift works
> like `async Void` in C# and never support something like `async Task`
> in C#.
>
> I think 2 is impermissible. For example, handling completion events of
> asynchronous operations without result values needs something like
> `async Task` in C#. However, with 1, we lose the benefit of static
> checks by the compiler. Because both of `fooAsync()` without `await`
> and `await fooAsync()` are allowed, even if we want it to work like
> `async Task` in C# and forget to mark `await`, the compiler tell us
> nothing and it works like `async Void` in C#. It causes unexpected
> behaviors. It is hard to fix such kinds of bugs. So I think
> introducing `beginAsync` is better.
>
> --
> Yuta
>
>
> 2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution
> :
> > 2017-11-12 2:57 GMT+09:00 Adam Kemp :
> >>
> >>
> >>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa 
> wrote:
> >>>
> >>> If you replace `async` with `throws`, you can get answers.
> >>>
> >>>
>  Can you declare an async closure variable?
> >>>
> >>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
> >>>
> >>>
>  Can a non-async closure be passed to a function expecting a async
> closure?
> >>>
> >>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
> >>> closure `() throws -> Void`.
> >>>
> >>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
> >>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
> >>> same way.
> >>>
> >>> To treat an async function as a sync function is legal. It is similar
> >>> to make a `Promise` by `Promise(value)` which is completed
> >>> immediately.
> >>>
> >>>
>  Can an async closure be passed to a function expecting a non-async
> closure?
> >>>
> >>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
> >>> passing `() throws -> Void` to a function expecting `() -> Void` is
> >>> not allowed.
> >>
> >> But why not? Just asserting that it must work the same as throws
> >> is not a convincing argument. You have to justify why it must work
> >> that way. I think there is good reason to allow it, which I have
> described.
> >> What reason is there to disallow it?
> >
> > `() async -> Void` needs to be called with `await` because it prevents
> > us from forgetting handling asynchronous operations.
> >
> > If we use callbacks to handle asynchronous operations, it is shown to
> > us by a compiler as a compilation error.
> >
> > ```
> > func fooAsync(_ handler: () -> Void) -> Void { ... }
> >
> > fooAsync() // compilation error
> >
> > fooAsync {
> >   // handles a completion event here
> > }
> > ```
> >
> > With proposed `async/await`, it is realized similarly like below.
> >
> > ```
> > func fooAsync() async -> Void { ... }
> >
> > fooAsync() // compilation error
> >
> > await fooAsync()
> > // handles a completion event here
> > ```
> >
> > However, if async void functions work like `beginAsync`, we can easily
> > forget it and it can cause unexpected behaviors.
> >
> > ```
> > func fooAsync() async -> Void { ... }
> >
> > fooAsync() // OK
> > // hard to know this line is executed asynchronously
> > ```
> >
> > Readability also suffers seriously. If we don't know `bar` in the
> > following code is a async function, it is impossible to expect lines
> > after `baz()` are executed asynchronously.
> >
> > ```
> > foo()
> > bar()
> > baz()
> > qux()
> > ```
> >
> >
>  It’s weird to me that we would allow you to have async void closures

Re: [swift-evolution] async void

2017-11-12 Thread Yuta Koshizawa via swift-evolution
Sorry, I had got some confusion. Please let me retry to explain.

As you said, C# provides three kinds of async functions: `async Void`,
`async Task` and `async Task`. All of them are necessary and
Swift should provide same functionalities.

When we think about `async/await` in Swift, because we have already
had `throws/try`, it is desired that `async/await` in Swift is
consistent with `throws/try`. So it is better to have `async/await`
without introducing a type like `Task` (or `Promise`).

Even if we employ `async/await` without `Task`, Swift has to provides
functionalities to implement "three kinds of async functions" in C#.
However if `async -> Void` in Swift works similarly to `async Void` in
C#, how can we express ones like `async Task` in C#? I think there are
two possibilities:

1. Calling `async -> Void` functions without `await` in Swift works
like `async Void` in C# and calling them *with* `await` works like
`async Task` in C#.
2. Calling `async -> Void` functions without `await` in Swift works
like `async Void` in C# and never support something like `async Task`
in C#.

I think 2 is impermissible. For example, handling completion events of
asynchronous operations without result values needs something like
`async Task` in C#. However, with 1, we lose the benefit of static
checks by the compiler. Because both of `fooAsync()` without `await`
and `await fooAsync()` are allowed, even if we want it to work like
`async Task` in C# and forget to mark `await`, the compiler tell us
nothing and it works like `async Void` in C#. It causes unexpected
behaviors. It is hard to fix such kinds of bugs. So I think
introducing `beginAsync` is better.

--
Yuta


2017-11-12 10:23 GMT+09:00 Yuta Koshizawa via swift-evolution
:
> 2017-11-12 2:57 GMT+09:00 Adam Kemp :
>>
>>
>>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa  wrote:
>>>
>>> If you replace `async` with `throws`, you can get answers.
>>>
>>>
 Can you declare an async closure variable?
>>>
>>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
>>>
>>>
 Can a non-async closure be passed to a function expecting a async closure?
>>>
>>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
>>> closure `() throws -> Void`.
>>>
>>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
>>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
>>> same way.
>>>
>>> To treat an async function as a sync function is legal. It is similar
>>> to make a `Promise` by `Promise(value)` which is completed
>>> immediately.
>>>
>>>
 Can an async closure be passed to a function expecting a non-async closure?
>>>
>>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
>>> passing `() throws -> Void` to a function expecting `() -> Void` is
>>> not allowed.
>>
>> But why not? Just asserting that it must work the same as throws
>> is not a convincing argument. You have to justify why it must work
>> that way. I think there is good reason to allow it, which I have described.
>> What reason is there to disallow it?
>
> `() async -> Void` needs to be called with `await` because it prevents
> us from forgetting handling asynchronous operations.
>
> If we use callbacks to handle asynchronous operations, it is shown to
> us by a compiler as a compilation error.
>
> ```
> func fooAsync(_ handler: () -> Void) -> Void { ... }
>
> fooAsync() // compilation error
>
> fooAsync {
>   // handles a completion event here
> }
> ```
>
> With proposed `async/await`, it is realized similarly like below.
>
> ```
> func fooAsync() async -> Void { ... }
>
> fooAsync() // compilation error
>
> await fooAsync()
> // handles a completion event here
> ```
>
> However, if async void functions work like `beginAsync`, we can easily
> forget it and it can cause unexpected behaviors.
>
> ```
> func fooAsync() async -> Void { ... }
>
> fooAsync() // OK
> // hard to know this line is executed asynchronously
> ```
>
> Readability also suffers seriously. If we don't know `bar` in the
> following code is a async function, it is impossible to expect lines
> after `baz()` are executed asynchronously.
>
> ```
> foo()
> bar()
> baz()
> qux()
> ```
>
>
 It’s weird to me that we would allow you to have async void closures but 
 not async void functions
>>>
>>> I am not sure what you mean. "async void closures" and "async void
>>> functions" have a same type. Following two are almost same.
>>>
>>> ```
>>> func foo() async -> Void { ... }
>>> let foo: () async -> Void = { ... }
>>> ```
>>
>> What started this thread is my suggestion that you should be able to write
>> an async void function. The current proposal doesn’t allow that. That’s why
>> you have to use beginAsync.
>>
>> I don’t think that makes sense. It sounds like you also think that would be 
>> strange,
>> hence your assumption that you could.
>
> By the reasons I wrote above, we need `await` even for async void
> functions for checks by compilers. Then it is required to 

Re: [swift-evolution] async void

2017-11-11 Thread Yuta Koshizawa via swift-evolution
2017-11-12 2:57 GMT+09:00 Adam Kemp :
>
>
>> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa  wrote:
>>
>> If you replace `async` with `throws`, you can get answers.
>>
>>
>>> Can you declare an async closure variable?
>>
>> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
>>
>>
>>> Can a non-async closure be passed to a function expecting a async closure?
>>
>> Yes. Like we can pass `() -> Void` to a function expecting a throwing
>> closure `() throws -> Void`.
>>
>> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
>> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
>> same way.
>>
>> To treat an async function as a sync function is legal. It is similar
>> to make a `Promise` by `Promise(value)` which is completed
>> immediately.
>>
>>
>>> Can an async closure be passed to a function expecting a non-async closure?
>>
>> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
>> passing `() throws -> Void` to a function expecting `() -> Void` is
>> not allowed.
>
> But why not? Just asserting that it must work the same as throws
> is not a convincing argument. You have to justify why it must work
> that way. I think there is good reason to allow it, which I have described.
> What reason is there to disallow it?

`() async -> Void` needs to be called with `await` because it prevents
us from forgetting handling asynchronous operations.

If we use callbacks to handle asynchronous operations, it is shown to
us by a compiler as a compilation error.

```
func fooAsync(_ handler: () -> Void) -> Void { ... }

fooAsync() // compilation error

fooAsync {
  // handles a completion event here
}
```

With proposed `async/await`, it is realized similarly like below.

```
func fooAsync() async -> Void { ... }

fooAsync() // compilation error

await fooAsync()
// handles a completion event here
```

However, if async void functions work like `beginAsync`, we can easily
forget it and it can cause unexpected behaviors.

```
func fooAsync() async -> Void { ... }

fooAsync() // OK
// hard to know this line is executed asynchronously
```

Readability also suffers seriously. If we don't know `bar` in the
following code is a async function, it is impossible to expect lines
after `baz()` are executed asynchronously.

```
foo()
bar()
baz()
qux()
```


>>> It’s weird to me that we would allow you to have async void closures but 
>>> not async void functions
>>
>> I am not sure what you mean. "async void closures" and "async void
>> functions" have a same type. Following two are almost same.
>>
>> ```
>> func foo() async -> Void { ... }
>> let foo: () async -> Void = { ... }
>> ```
>
> What started this thread is my suggestion that you should be able to write
> an async void function. The current proposal doesn’t allow that. That’s why
> you have to use beginAsync.
>
> I don’t think that makes sense. It sounds like you also think that would be 
> strange,
> hence your assumption that you could.

By the reasons I wrote above, we need `await` even for async void
functions for checks by compilers. Then it is required to provide a
way to write entry points of async functions. That is `beginAsync`.

--
Yuta
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] async void

2017-11-11 Thread Adam Kemp via swift-evolution


> On Nov 11, 2017, at 6:24 AM, Yuta Koshizawa  wrote:
> 
> If you replace `async` with `throws`, you can get answers.
> 
> 
>> Can you declare an async closure variable?
> 
> Yes. Like `let throwingClosure:() throws -> Void = { ... }`.
> 
> 
>> Can a non-async closure be passed to a function expecting a async closure?
> 
> Yes. Like we can pass `() -> Void` to a function expecting a throwing
> closure `() throws -> Void`.
> 
> It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
> -> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
> same way.
> 
> To treat an async function as a sync function is legal. It is similar
> to make a `Promise` by `Promise(value)` which is completed
> immediately.
> 
> 
>> Can an async closure be passed to a function expecting a non-async closure?
> 
> No. `() -> Void` is a subtype of `() async -> Void`. It is same as
> passing `() throws -> Void` to a function expecting `() -> Void` is
> not allowed.

But why not? Just asserting that it must work the same as throws is not a 
convincing argument. You have to justify why it must work that way. I think 
there is good reason to allow it, which I have described. What reason is there 
to disallow it?

>> It’s weird to me that we would allow you to have async void closures but not 
>> async void functions
> 
> I am not sure what you mean. "async void closures" and "async void
> functions" have a same type. Following two are almost same.
> 
> ```
> func foo() async -> Void { ... }
> let foo: () async -> Void = { ... }
> ```

What started this thread is my suggestion that you should be able to write an 
async void function. The current proposal doesn’t allow that. That’s why you 
have to use beginAsync.

I don’t think that makes sense. It sounds like you also think that would be 
strange, hence your assumption that you could.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] async void

2017-11-11 Thread Yuta Koshizawa via swift-evolution
If you replace `async` with `throws`, you can get answers.


> Can you declare an async closure variable?

Yes. Like `let throwingClosure:() throws -> Void = { ... }`.


> Can a non-async closure be passed to a function expecting a async closure?

Yes. Like we can pass `() -> Void` to a function expecting a throwing
closure `() throws -> Void`.

It is possible because `(Foo) throws -> Bar` is a supertype of `(Foo)
-> Bar`. `(Foo) async -> Bar` is a supertype of `(Foo) -> Bar` in the
same way.

To treat an async function as a sync function is legal. It is similar
to make a `Promise` by `Promise(value)` which is completed
immediately.


> Can an async closure be passed to a function expecting a non-async closure?

No. `() -> Void` is a subtype of `() async -> Void`. It is same as
passing `() throws -> Void` to a function expecting `() -> Void` is
not allowed.


> It’s weird to me that we would allow you to have async void closures but not 
> async void functions

I am not sure what you mean. "async void closures" and "async void
functions" have a same type. Following two are almost same.

```
func foo() async -> Void { ... }
let foo: () async -> Void = { ... }
```

--
Yuta


2017-11-11 11:02 GMT+09:00 Adam Kemp :
> I’m not sure that answered my questions.
>
> Can I do this?
>
> let asyncClosure:() async -> Void = { await doSomethingAsync() } // Can you
> declare an async closure variable?
>
> beginAsync(asyncClosure)
>
>
> What about this?
>
> let syncClosure:() -> Void = { doSomethingSync() }
>
> beginAsync(syncClosure) // Can a non-async closure be passed to a function
> expecting a async closure?
>
>
> And this?
>
>
> func callSyncClosure(_ closure:() -> ()) { closure() }
>
>
> let asyncClosure:() async -> Void = { await doSomethingAsync() }
>
>
> callSyncClosure(asyncClosure) // Can an async closure be passed to a
> function expecting a non-async closure?
>
>
> Here are my thoughts on each of these:
>
> Can you declare an async closure variable? If async is part of the type then
> it would be very strange not to allow this. I think the proposal implies
> that you can, but only by way of an example about inferring whether a
> closure is async or not.
>
> Can a non-async closure be passed to a function expecting a sync closure?
> This seems like an obvious conversion. I feel like disallowing this would
> probably make things harder, but I haven’t thought it through enough to say
> exactly how. Are there reasons that this shouldn’t work, though?
>
> Can an async closure be passed to a function expecting a sync closure? This
> may be controversial, but I think this should be allowed too. I think a
> caller that expects a void-returning synchronous function should be able to
> call an async function and treat it as a call-and-forget.
>
> It’s weird to me that we would allow you to have async void closures but not
> async void functions, but in order to support beginAsync we have to have
> async void closures. So if we can make that work then why couldn’t we just
> make async void functions work and dispense with beginAsync entirely?
>
> On Nov 10, 2017, at 1:38 AM, Yuta Koshizawa via swift-evolution
>  wrote:
>
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?
>
>
> It has been already realized for `throws`.
>
> ```
> // This works in Swift 4
> func foo(_ f: (Bar) throws -> Baz)
>
> // This can be checked in the same way
> func foo(_ f: (Bar) async -> Baz)
> ```
>
> Proposed `async/await` in Swift are analogous to `throws/try`. So a
> lot of things about `async/await` can be imagined when we think about
> `throws/try`. It is also true for `(Foo) async -> Void`. We can use it
> in the same way as we use `(Foo) throws -> Void`.
>
> `async/await` as an analogy to `throws/try` works well because both of
> them can be mapped to monads. `throws` is similar to `Result` and
> `async` is similar to `Promise` ( `Future` ).
>
> ```
> // `a` and `b` are similar
> func a() throws -> Int
> func b() -> Result
>
> // `c` and `d` are similar
> func c() async -> Int
> func d() -> Promise
>
> // `a` : `b` == `c` : `d`
> // `a` : `c` == `b` : `d`
> ```
>
> `try` and `await` are also similar to `flatMap`. ( I think most
> popular `Promise` is one in JavaScript. Although it does not have
> `flatMap`, its `then` method can be considered as `flatMap`. )
>
> ```
> let x = try a()
> // uses `x` here
>
> b().flatMap { x in
>  // uses `x` here
> }
>
> let y = await c()
> // uses `y` here
>
> d().flatMap { y in
>  // uses `y` here
> }
> ```
>
> So `throws` : `try` : `Result` == `async` : `await` : `Promise` and
> `throws` : `async` == `try` : `await` == `Result` : `Promise`. I think
> those rel

Re: [swift-evolution] async void

2017-11-10 Thread Adam Kemp via swift-evolution
I’m not sure that answered my questions.

Can I do this?

let asyncClosure:() async -> Void = { await doSomethingAsync() } // Can you 
declare an async closure variable?

beginAsync(asyncClosure)

What about this?

let syncClosure:() -> Void = { doSomethingSync() }

beginAsync(syncClosure) // Can a non-async closure be passed to a function 
expecting a async closure?

And this?

func callSyncClosure(_ closure:() -> ()) { closure() }

let asyncClosure:() async -> Void = { await doSomethingAsync() }

callSyncClosure(asyncClosure) // Can an async closure be passed to a function 
expecting a non-async closure?

Here are my thoughts on each of these:

Can you declare an async closure variable? If async is part of the type then it 
would be very strange not to allow this. I think the proposal implies that you 
can, but only by way of an example about inferring whether a closure is async 
or not.

Can a non-async closure be passed to a function expecting a sync closure? This 
seems like an obvious conversion. I feel like disallowing this would probably 
make things harder, but I haven’t thought it through enough to say exactly how. 
Are there reasons that this shouldn’t work, though?

Can an async closure be passed to a function expecting a sync closure? This may 
be controversial, but I think this should be allowed too. I think a caller that 
expects a void-returning synchronous function should be able to call an async 
function and treat it as a call-and-forget.

It’s weird to me that we would allow you to have async void closures but not 
async void functions, but in order to support beginAsync we have to have async 
void closures. So if we can make that work then why couldn’t we just make async 
void functions work and dispense with beginAsync entirely?

> On Nov 10, 2017, at 1:38 AM, Yuta Koshizawa via swift-evolution 
>  wrote:
> 
>> I’m not sure how the proposed design handles type checking for async
>> closures. Is async part of the type? Can I declare a local closure variable
>> as async? What are the rules for conversion between async and non-async
>> closures? Is it a warning or error to use a closure literal without an async
>> keyword that is assigned to an async closure variable or passed as an async
>> closure argument?
> 
> It has been already realized for `throws`.
> 
> ```
> // This works in Swift 4
> func foo(_ f: (Bar) throws -> Baz)
> 
> // This can be checked in the same way
> func foo(_ f: (Bar) async -> Baz)
> ```
> 
> Proposed `async/await` in Swift are analogous to `throws/try`. So a
> lot of things about `async/await` can be imagined when we think about
> `throws/try`. It is also true for `(Foo) async -> Void`. We can use it
> in the same way as we use `(Foo) throws -> Void`.
> 
> `async/await` as an analogy to `throws/try` works well because both of
> them can be mapped to monads. `throws` is similar to `Result` and
> `async` is similar to `Promise` ( `Future` ).
> 
> ```
> // `a` and `b` are similar
> func a() throws -> Int
> func b() -> Result
> 
> // `c` and `d` are similar
> func c() async -> Int
> func d() -> Promise
> 
> // `a` : `b` == `c` : `d`
> // `a` : `c` == `b` : `d`
> ```
> 
> `try` and `await` are also similar to `flatMap`. ( I think most
> popular `Promise` is one in JavaScript. Although it does not have
> `flatMap`, its `then` method can be considered as `flatMap`. )
> 
> ```
> let x = try a()
> // uses `x` here
> 
> b().flatMap { x in
>  // uses `x` here
> }
> 
> let y = await c()
> // uses `y` here
> 
> d().flatMap { y in
>  // uses `y` here
> }
> ```
> 
> So `throws` : `try` : `Result` == `async` : `await` : `Promise` and
> `throws` : `async` == `try` : `await` == `Result` : `Promise`. I think
> those relations are beautiful and proposed `async/await` fits well to
> Swift because we have already had `throws/try`.
> 
> --
> Yuta
> 
> 
> 2017-11-10 6:45 GMT+09:00 Adam Kemp via swift-evolution
> :
>> 
>> On Nov 9, 2017, at 11:02 AM, Wallacy  wrote:
>> 
>> So for me, this:
>> 
>> func OnButtonClicked(_ sender:AnyObject) {
>> 
>>let button = sender as! UIButton
>>button.isEnabled = false
>>beginAsync {
>>await DoSomethingAsync()
>>button.isEnabled = true
>>}
>> }
>> 
>> 
>> Does not make any sense... Because await will not block the thread we can
>> assume (like the exemple on proposal) that compiler will actually do the
>> same what we will do using GDC and pick everyone to until the context ends
>> and encapsulate as completion handle to the away call.
>> 
>> 
>> I don’t understand what you’re saying here. In terms of GCD the above code
>> is basically equivalent to this:
>> 
>> func buttonClicked(_ sender:AnyObject) {
>>let button = sender as! UIButton
>>button.isEnabled = false
>>doSomethingAsync { // completion callback, assume it’s on the main queue
>>button.isEnabled = true
>>}
>> }
>> 
>> 
>> And this one:
>> 
>> @IBAction func buttonDidClick(sender:AnyObject) {
>>  beginAsync {
>>let image = await proce

Re: [swift-evolution] async void

2017-11-10 Thread Yuta Koshizawa via swift-evolution
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?

It has been already realized for `throws`.

```
// This works in Swift 4
func foo(_ f: (Bar) throws -> Baz)

// This can be checked in the same way
func foo(_ f: (Bar) async -> Baz)
```

Proposed `async/await` in Swift are analogous to `throws/try`. So a
lot of things about `async/await` can be imagined when we think about
`throws/try`. It is also true for `(Foo) async -> Void`. We can use it
in the same way as we use `(Foo) throws -> Void`.

`async/await` as an analogy to `throws/try` works well because both of
them can be mapped to monads. `throws` is similar to `Result` and
`async` is similar to `Promise` ( `Future` ).

```
// `a` and `b` are similar
func a() throws -> Int
func b() -> Result

// `c` and `d` are similar
func c() async -> Int
func d() -> Promise

// `a` : `b` == `c` : `d`
// `a` : `c` == `b` : `d`
```

`try` and `await` are also similar to `flatMap`. ( I think most
popular `Promise` is one in JavaScript. Although it does not have
`flatMap`, its `then` method can be considered as `flatMap`. )

```
let x = try a()
// uses `x` here

b().flatMap { x in
  // uses `x` here
}

let y = await c()
// uses `y` here

d().flatMap { y in
  // uses `y` here
}
```

So `throws` : `try` : `Result` == `async` : `await` : `Promise` and
`throws` : `async` == `try` : `await` == `Result` : `Promise`. I think
those relations are beautiful and proposed `async/await` fits well to
Swift because we have already had `throws/try`.

--
Yuta


2017-11-10 6:45 GMT+09:00 Adam Kemp via swift-evolution
:
>
> On Nov 9, 2017, at 11:02 AM, Wallacy  wrote:
>
> So for me, this:
>
> func OnButtonClicked(_ sender:AnyObject) {
>
> let button = sender as! UIButton
> button.isEnabled = false
> beginAsync {
> await DoSomethingAsync()
> button.isEnabled = true
> }
> }
>
>
> Does not make any sense... Because await will not block the thread we can
> assume (like the exemple on proposal) that compiler will actually do the
> same what we will do using GDC and pick everyone to until the context ends
> and encapsulate as completion handle to the away call.
>
>
> I don’t understand what you’re saying here. In terms of GCD the above code
> is basically equivalent to this:
>
> func buttonClicked(_ sender:AnyObject) {
> let button = sender as! UIButton
> button.isEnabled = false
> doSomethingAsync { // completion callback, assume it’s on the main queue
> button.isEnabled = true
> }
> }
>
>
> And this one:
>
> @IBAction func buttonDidClick(sender:AnyObject) {
>   beginAsync {
> let image = await processImageData()
> // Do the update on the main thread/queue since it owns imageView.
> mainQ.async {
>   imageView.image = image
> }
>   }
> }
>
>
>
> Does not make any sense too.
>
> The only way to await to do not block the thread is make a early return like
> beginAsync and encapsulate as completion handle the rest of the code.
>
>
> This is why “await” can only be used in a function that is marked as
> “async”. The “async” keyword tells the compiler that this function will be
> broken up into parts, and its return value will be produced asynchronously.
>
> One thing that might be confusing is that in the examples using “beginAsync”
> the trailing closure is the async function. That’s not obvious because
> there’s no “async” keyword, but it’s there in the signature of the closure
> argument:
>
> func beginAsync(_ body: () async throws -> Void) rethrows -> Void
>
>
> I’m not sure how the proposed design handles type checking for async
> closures. Is async part of the type? Can I declare a local closure variable
> as async? What are the rules for conversion between async and non-async
> closures? Is it a warning or error to use a closure literal without an async
> keyword that is assigned to an async closure variable or passed as an async
> closure argument?
>
> C# dodges all of these issues because async isn't part of the type system.
> Closures that don’t return anything can be declared async just like void
> functions, and code that uses void-returning closures doesn’t need to care
> whether the implementation is async or not.
>
>
>
> ___
> 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


Re: [swift-evolution] async void

2017-11-09 Thread Adam Kemp via swift-evolution

> On Nov 9, 2017, at 11:02 AM, Wallacy  wrote:
> 
> So for me, this:
> 
> func OnButtonClicked(_ sender:AnyObject) {
> let button = sender as! UIButton
> button.isEnabled = false
> beginAsync {
> await DoSomethingAsync()
> button.isEnabled = true
> }
> }
> 
> Does not make any sense... Because await will not block the thread we can 
> assume (like the exemple on proposal) that compiler will actually do the same 
> what we will do using GDC and pick everyone to until the context ends and 
> encapsulate as completion handle to the away call.

I don’t understand what you’re saying here. In terms of GCD the above code is 
basically equivalent to this:

func buttonClicked(_ sender:AnyObject) {
let button = sender as! UIButton
button.isEnabled = false
doSomethingAsync { // completion callback, assume it’s on the main queue
button.isEnabled = true
}
}

> And this one:
> 
> @IBAction func buttonDidClick(sender:AnyObject) {
>   beginAsync {
> let image = await processImageData()
> // Do the update on the main thread/queue since it owns imageView.
> mainQ.async {
>   imageView.image = image
> }
>   }
> }
> 
> 
> Does not make any sense too.
> 
> The only way to await to do not block the thread is make a early return like 
> beginAsync and encapsulate as completion handle the rest of the code. 

This is why “await” can only be used in a function that is marked as “async”. 
The “async” keyword tells the compiler that this function will be broken up 
into parts, and its return value will be produced asynchronously.

One thing that might be confusing is that in the examples using “beginAsync” 
the trailing closure is the async function. That’s not obvious because there’s 
no “async” keyword, but it’s there in the signature of the closure argument:

func beginAsync(_ body: () async throws -> Void) rethrows -> Void

I’m not sure how the proposed design handles type checking for async closures. 
Is async part of the type? Can I declare a local closure variable as async? 
What are the rules for conversion between async and non-async closures? Is it a 
warning or error to use a closure literal without an async keyword that is 
assigned to an async closure variable or passed as an async closure argument?

C# dodges all of these issues because async isn't part of the type system. 
Closures that don’t return anything can be declared async just like void 
functions, and code that uses void-returning closures doesn’t need to care 
whether the implementation is async or not.

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] async void

2017-11-09 Thread Wallacy via swift-evolution
Before i make a comment on this topic i need to confirm something:

On original proposal, this:

func processImageData1(completionBlock: (result: Image) -> Void) {
loadWebResource("dataprofile.txt") { dataResource in
loadWebResource("imagedata.dat") { imageResource in
decodeImage(dataResource, imageResource) { imageTmp in
dewarpAndCleanupImage(imageTmp) { imageResult in
completionBlock(imageResult)
}
}
}
}
}


Is converted to this:

func processImageData1() async -> Image {
let dataResource  = await loadWebResource("dataprofile.txt")
let imageResource = await loadWebResource("imagedata.dat")
let imageTmp  = await decodeImage(dataResource, imageResource)
let imageResult   = await dewarpAndCleanupImage(imageTmp)
return imageResult
}



And has other sentences explain that await will not block the thread etc...

So for me, this:

func OnButtonClicked(_ sender:AnyObject) {

let button = sender as! UIButton
button.isEnabled = false
beginAsync {
await DoSomethingAsync()
button.isEnabled = true
}
}


Does not make any sense... Because await will not block the thread we can
assume (like the exemple on proposal) that compiler will actually do the
same what we will do using GDC and pick everyone to until the context ends
and encapsulate as completion handle to the away call.

So we will only have this:

func OnButtonClicked(_ sender:AnyObject) {

let button = sender as! UIButton

button.isEnabled = false

await DoSomethingAsync()

button.isEnabled = true

}


I don't know how to handle reentrante or something like that, but  the
proposal give me the impression this behavior.

In the other way, await will block the thread!

I know the proposal give us this exemple:

@IBAction func buttonDidClick(sender:AnyObject) {
  // 1  beginAsync {
// 2let image = await processImage()
imageView.image = image
  }
  // 3}



But this is different, because "3" will be fired before "2".

And this one:

@IBAction func buttonDidClick(sender:AnyObject) {
  beginAsync {
let image = await processImageData()
// Do the update on the main thread/queue since it owns imageView.
   mainQ.async {
  imageView.image = image
}
  }
}



Does not make any sense too.

The only way to await to do not block the thread is make a early return
like beginAsync and encapsulate as completion handle the rest of the code.

If not, i don't see how the first exemple of the proposal will be made.

Em qua, 8 de nov de 2017 às 15:55, Adam Kemp via swift-evolution <
swift-evolution@swift.org> escreveu:

> (I changed the subject since it’s not really the same topic)
>
> The short answer is that this code has the same problem even without async
> void:
>
> func sendMessage() {
> beginAsync {
> // …
> }
> }
>
> func onButtonClick() {
> sendMessage()
> showAlert("message sent")
> }
>
>
> If you want someone to be able to wait for something to finish then you
> make your function awaitable. So what does that mean for an async function
> that doesn’t really return anything? To understand what I’m thinking it
> helps to understand how C# does it, since that’s the model I’m proposing,
> and I think it works really well. In C# it works like this:
>
> void NoReturn() { }
> int IntReturn() { return 0; }
>
> async Task NoReturnAsync() { await Task.Yield(); }
> async Task IntReturnAsync() { await Task.Yield(); return 0; }
>
> async void NoReturnAsyncVoid() { await Task.Yield(); }
>
> async Task Caller()
> {
> NoReturn();
> int i = IntReturn();
> await NoReturnAsync();
> int j = await IntReturnAsync();
>
> NoReturnAsync(); // this cannot be awaited
> }
>
>
> An important difference is that in C# the async keyword does not make a
> function awaitable. Notice how NoReturnAsyncVoid is marked as “async”, but
> the caller cannot use “await” with it. So what do you do if you want to
> wait for it to finish, like in your example? Well notice that another
> function NoReturnAsync doesn’t actually appear to return anything, even
> though its return type is Task. The compiler transforms the function into
> pieces where the first piece (the one actually called by the caller)
> returns a Task object. A bare Task is only used for waiting for completion,
> whereas a Task also holds a return value. When you make a function that
> returns T async then you change the return type to Task. When you make a
> void function async and want to allow the caller to wait for it to finish
> then you change the void to Task. When you make a void function async but
> want the caller to not wait for it to finish then you leave it as void.
>
> This is subtle, but consider this alternative form:
>
> void NoReturn() { }
> int IntReturn() { return 0; }
>
> Task NoReturnAsync() { return Task.Yield(); }
> Task IntReturnAsync() { return Task.Yield(); return 0; }
>
> void

Re: [swift-evolution] async void

2017-11-09 Thread Nobuo Saito via swift-evolution
Hi,
I have two opinion about async void function,

1. I think async(or sync) function should has a returning value even if
type is void.
```
let result = await somethingAsyncVoid()
```
In this case the `result` will available when `someThingAsyncVoid` was
completed.
Someone can omit it, but it should be usable for other one who want to use
it.
Even if someone omit returning value in async void function, the function
should return result(void) when process was finished.


2. About async throws function.
We should consider about combine `async` and `throws` function. Some
failure may happen asynchronously, we cannot solve the `async error` if we
ignore await async void function.

2017-11-09 2:55 GMT+09:00 Adam Kemp via swift-evolution <
swift-evolution@swift.org>:

> (I changed the subject since it’s not really the same topic)
>
> The short answer is that this code has the same problem even without async
> void:
>
> func sendMessage() {
> beginAsync {
> // …
> }
> }
>
> func onButtonClick() {
> sendMessage()
> showAlert("message sent")
> }
>
>
> If you want someone to be able to wait for something to finish then you
> make your function awaitable. So what does that mean for an async function
> that doesn’t really return anything? To understand what I’m thinking it
> helps to understand how C# does it, since that’s the model I’m proposing,
> and I think it works really well. In C# it works like this:
>
> void NoReturn() { }
> int IntReturn() { return 0; }
>
> async Task NoReturnAsync() { await Task.Yield(); }
> async Task IntReturnAsync() { await Task.Yield(); return 0; }
>
> async void NoReturnAsyncVoid() { await Task.Yield(); }
>
> async Task Caller()
> {
> NoReturn();
> int i = IntReturn();
> await NoReturnAsync();
> int j = await IntReturnAsync();
>
> NoReturnAsync(); // this cannot be awaited
> }
>
>
> An important difference is that in C# the async keyword does not make a
> function awaitable. Notice how NoReturnAsyncVoid is marked as “async”, but
> the caller cannot use “await” with it. So what do you do if you want to
> wait for it to finish, like in your example? Well notice that another
> function NoReturnAsync doesn’t actually appear to return anything, even
> though its return type is Task. The compiler transforms the function into
> pieces where the first piece (the one actually called by the caller)
> returns a Task object. A bare Task is only used for waiting for completion,
> whereas a Task also holds a return value. When you make a function that
> returns T async then you change the return type to Task. When you make a
> void function async and want to allow the caller to wait for it to finish
> then you change the void to Task. When you make a void function async but
> want the caller to not wait for it to finish then you leave it as void.
>
> This is subtle, but consider this alternative form:
>
> void NoReturn() { }
> int IntReturn() { return 0; }
>
> Task NoReturnAsync() { return Task.Yield(); }
> Task IntReturnAsync() { return Task.Yield(); return 0; }
>
> void NoReturnAsyncVoid() { Task.Yield(); }
>
> async Task Caller()
> {
> NoReturn();
> int i = IntReturn();
> await NoReturnAsync();
> int j = await IntReturnAsync();
>
> NoReturnAsync(); // this cannot be awaited
> }
>
>
> I changed all of the “async" functions above except for Caller by removing
> the “async” keyword and (where applicable) added return statements. Now
> none of those functions is async, but they are functionally equivalent.
> Notice that the async Caller (which I didn’t change at all) can still await
> the ones that return Task or Task. That’s because, again, in C# the
> async keyword does not mean “this can be awaited”. Being able to await a
> function call is orthogonal to whether that function is marked as async.
>
> Async means only one thing: that function can use the await keyword, and
> it will be decomposed by the compiler accordingly. So what can you await?
> Anything that’s “awaitable”. :) Basically if the return type of the
> function has a GetAwaiter method that returns a type that has a few
> properties and methods then you can use await on that function. This is
> described here:  com/pfxteam/2011/01/13/await-anything/>. Task happens to have a
> GetAwaiter ( threading.tasks.task.getawaiter(v=vs.110).aspx>) method that returns a
> TaskAwaiter ( compilerservices.taskawaiter(v=vs.110).aspx>), which happens to have an
> IsCompleted property and GetResult and OnCompleted methods.
>
> You can make any type awaitable by supplying a suitable GetAwaiter
> implementation, even using an extension method. I think this could probably
> be done with protocols and extensions in Swift.
>
> Back to the problem you described: wouldn’t an async void method be
> confusing to callers who expect it to finish before returning? Obvi

Re: [swift-evolution] async void

2017-11-08 Thread Adam Kemp via swift-evolution
(I changed the subject since it’s not really the same topic)

The short answer is that this code has the same problem even without async void:

func sendMessage() {
beginAsync {
// …
}
}

func onButtonClick() {
sendMessage()
showAlert("message sent")
}

If you want someone to be able to wait for something to finish then you make 
your function awaitable. So what does that mean for an async function that 
doesn’t really return anything? To understand what I’m thinking it helps to 
understand how C# does it, since that’s the model I’m proposing, and I think it 
works really well. In C# it works like this:

void NoReturn() { }
int IntReturn() { return 0; }

async Task NoReturnAsync() { await Task.Yield(); }
async Task IntReturnAsync() { await Task.Yield(); return 0; }

async void NoReturnAsyncVoid() { await Task.Yield(); }

async Task Caller()
{
NoReturn();
int i = IntReturn();
await NoReturnAsync();
int j = await IntReturnAsync();

NoReturnAsync(); // this cannot be awaited
}

An important difference is that in C# the async keyword does not make a 
function awaitable. Notice how NoReturnAsyncVoid is marked as “async”, but the 
caller cannot use “await” with it. So what do you do if you want to wait for it 
to finish, like in your example? Well notice that another function 
NoReturnAsync doesn’t actually appear to return anything, even though its 
return type is Task. The compiler transforms the function into pieces where the 
first piece (the one actually called by the caller) returns a Task object. A 
bare Task is only used for waiting for completion, whereas a Task also holds 
a return value. When you make a function that returns T async then you change 
the return type to Task. When you make a void function async and want to 
allow the caller to wait for it to finish then you change the void to Task. 
When you make a void function async but want the caller to not wait for it to 
finish then you leave it as void.

This is subtle, but consider this alternative form:

void NoReturn() { }
int IntReturn() { return 0; }

Task NoReturnAsync() { return Task.Yield(); }
Task IntReturnAsync() { return Task.Yield(); return 0; }

void NoReturnAsyncVoid() { Task.Yield(); }

async Task Caller()
{
NoReturn();
int i = IntReturn();
await NoReturnAsync();
int j = await IntReturnAsync();

NoReturnAsync(); // this cannot be awaited
}

I changed all of the “async" functions above except for Caller by removing the 
“async” keyword and (where applicable) added return statements. Now none of 
those functions is async, but they are functionally equivalent. Notice that the 
async Caller (which I didn’t change at all) can still await the ones that 
return Task or Task. That’s because, again, in C# the async keyword does not 
mean “this can be awaited”. Being able to await a function call is orthogonal 
to whether that function is marked as async.

Async means only one thing: that function can use the await keyword, and it 
will be decomposed by the compiler accordingly. So what can you await? Anything 
that’s “awaitable”. :) Basically if the return type of the function has a 
GetAwaiter method that returns a type that has a few properties and methods 
then you can use await on that function. This is described here: 
>. Task 
happens to have a GetAwaiter 
(>)
 method that returns a TaskAwaiter 
()
 
,
 which happens to have an IsCompleted property and GetResult and OnCompleted 
methods.

You can make any type awaitable by supplying a suitable GetAwaiter 
implementation, even using an extension method. I think this could probably be 
done with protocols and extensions in Swift.

Back to the problem you described: wouldn’t an async void method be confusing 
to callers who expect it to finish before returning? Obviously if it’s a 
function that requires the caller to wait before continuing then it should be 
made awaitable. So in C# you wouldn’t make an async void function that you 
expected people to want to wait for, and in C# you have that choice: you can 
make an awaitable function that returns nothing to the awaiter.

The question, though, is “are there any use cases for an async function that 
doesn’t require its caller to wait for it?” Or, put another way, is there a use 
case for an async function that a caller can call as if it’s just any other 
void function? There definitely are multiple use cases for that, but the most 
impor