New async keyword usage

Hello Swift community,

I was really interested by the recent Task-based concurrency manifesto and Concrete proposal for async semantics in Swift.

Looking at beginAsync() and Futures, I had an idea for a new syntax based on the `async` keyword, I'd love to hear your feedback about this idea:
https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Thank you ! :)

Trevör

Interesting, its syntax seems to improve the "fire and forget" issue.

@IBAction func buttonClicked() {
  async downloadAndUpdateImageView()
}

In this case, the return Future<void> also does not need to be produced as
one of the compiler optimization.

Also,

func someAsyncFunc() async -> User {
  var userData = async downloadUserData() // userData is of type
Future<UserData> as we used async var image = async downloadImage() //
Equivalentely, image is of type Future<UIImage> return await
User(userData, image) // Await is somehow "unwarping" the futures back
into UserData and UIImage}

Makes sense to me, its pretty clear that downloadUserData and downloadImage can
be run in parallel, and the "sync point" is the only point when you need
the actual value.

What made me curious about this pattern is to do something like that:

func getUser() async -> User {
  var userData = async downloadUserData() var image = async
downloadImage() return async User(userData, image)}func
SomethingUsingUser() -> Void {
  var user = await getUser() //Only here printf(user.age > 21 ? "Let's
Drink" : "See you later!")
}// ORfunc Something2UsingUser() -> Void {
  var user = async getUser()
  var ageToDrink = getDrinkAge(); printf(user.get().age > ageToDrink ?
"Let's Drink" : "See you later!")
}// ORfunc Something2UsingUser() -> Void {
  var user = async getUser()
  var ageToDrink = async getDrinkAge();
  printf(await user.age > ageToDrink ? "Lets Drink" : "See you
latter!") // i dont know if this make sense}// OR maybe continue the
processfunc CanDrink() -> async bool {
  var user = async getUser()
  return async ()=>{ user.get().age > 21 } // Or other way to pass a
future computation.}

But the bast part is enable this:

func CanDrink() -> bool {
  var user = async getUser()
  var isOpenToDrink = barIsOpen()
  return isOpenToDrink ? (user.get().age > 21) : false // if bar is not
open, we dont need to evaluate user, and the task can be suspended
somehow.}

···

Em qui, 24 de ago de 2017 às 08:40, Trevör ANNE DENISE via swift-evolution < swift-evolution@swift.org> escreveu:

Hello Swift community,

I was really interested by the recent* Task-based concurrency manifesto*
and *Concrete proposal for async semantics in Swift.*

Looking at beginAsync() and Futures, I had an idea for a new syntax based
on the `async` keyword, I'd love to hear your feedback about this idea:

https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Thank you ! :)

Trevör
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Yes, it is entirely possible that we will want to provide more syntactic sugar than the proposal suggests: the proposal is intentionally designed to be minimal, so we can get it in place, get experience using it, then decide whether any specific syntactic pain point is significant enough to be worth adding additional sugar/complexity.

As has been mentioned in other threads, the hope is that “beginAsync” is actually extremely rare in practice. If that is the case, there is little point to sugaring it.

-Chris

···

On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift community,

I was really interested by the recent Task-based concurrency manifesto and Concrete proposal for async semantics in Swift.

Looking at beginAsync() and Futures, I had an idea for a new syntax based on the `async` keyword, I'd love to hear your feedback about this idea:
https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

I actually really like the idea of using ‘async' to start a computation in a non-blocking way. It is extremely common in real-world code to want to start a few computations/downloads at once in the background and then use the results together...

I think full-fledged futures could be a framework thing added on top, but what I would really love to see at the language level is that using ‘async’ just allows you to defer calling ‘await’. That is, you could get a value back from something called with async, but you would be forced to await that value before it could be used:

  var image = async downloadImage() //Image is type UIImage
  //Do something else here
  let size = await image.size //The compiler forces me to call await before I can actually use the value

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

I don’t think this is just sugar. It adds expressivity and control for a set of very common use-cases which aren’t fully supported by await alone.

Thanks,
Jon

···

On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift community,

I was really interested by the recent Task-based concurrency manifesto and Concrete proposal for async semantics in Swift.

Looking at beginAsync() and Futures, I had an idea for a new syntax based on the `async` keyword, I'd love to hear your feedback about this idea:
https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Thank you ! :)

Trevör
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?

  let a = async longCalculationA()
  let b = async longCalculationB() //b doesn’t wait for a to complete before starting
  let c = async longCalculationC() //c doesn’t wait for a or b
  let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

(Note: this is using my version of async below which doesn’t use futures)

Thanks,
Jon

···

On Aug 25, 2017, at 2:13 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:

I actually really like the idea of using ‘async' to start a computation in a non-blocking way. It is extremely common in real-world code to want to start a few computations/downloads at once in the background and then use the results together...

I think full-fledged futures could be a framework thing added on top, but what I would really love to see at the language level is that using ‘async’ just allows you to defer calling ‘await’. That is, you could get a value back from something called with async, but you would be forced to await that value before it could be used:

  var image = async downloadImage() //Image is type UIImage
  //Do something else here
  let size = await image.size //The compiler forces me to call await before I can actually use the value

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

I don’t think this is just sugar. It adds expressivity and control for a set of very common use-cases which aren’t fully supported by await alone.

Thanks,
Jon

On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello Swift community,

I was really interested by the recent Task-based concurrency manifesto and Concrete proposal for async semantics in Swift.

Looking at beginAsync() and Futures, I had an idea for a new syntax based on the `async` keyword, I'd love to hear your feedback about this idea:
https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Thank you ! :)

Trevör
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

Makes sense. But if i'm reading its right (and the original proposal too),
in this case we don't have only a syntax sugar, we actually gain another
ways to use.

First, because Future actually need another proposal, and beginAsync (to
me) does not apear to be that rare! "Fire and Forget" is pretty common when
we use Cocoa.

Second, because in this way we don't need to handle with Future anymore.
Like i see on the other Threads, people tends to believe the "Future" is a
more powerful, and only what is needed. Because that (not only that) we
cant prevent something like this:

func someAsyncFunc() -> Future<User>

So, after the Future class be implemented, we will need to handle with two
patterns at same time! Sometime we will use "await someAsyncFunc()" other
times, we will be forced to call someAsyncFunc().get().

Using only async/await is pretty easy to learn and teach. And the ability
to only "wrap" at asynchronous context and "unwrap" using only these two
keywords appear be worth.

Use async keyword to make a function asynchronous.
Use async keyword to make a closure asynchronous.
Use async keyword at call side to capture the "reference" and only "unwrap"
later. (maybe send to some other place too).
Use await to get the value from a async function/closure.

And after that, "Future" can be implement in any way because will not be a
public API anymore (I do not know, but there may also be some opportunities
for optimization as well), and we only need to care about when we need to
"keep the reference" from some async call.

And possibly, they will not need to create any Future type! The variable
type will be "async User" as long as it is not "unwrapped". (
suspend/defer/abandon still possible)

···

Em sex, 25 de ago de 2017 às 02:15, Chris Lattner via swift-evolution < swift-evolution@swift.org> escreveu:

On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution < > swift-evolution@swift.org> wrote:

Hello Swift community,

I was really interested by the recent* Task-based concurrency manifesto*
and *Concrete proposal for async semantics in Swift.*

Looking at beginAsync() and Futures, I had an idea for a new syntax based
on the `async` keyword, I'd love to hear your feedback about this idea:

https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Yes, it is entirely possible that we will want to provide more syntactic
sugar than the proposal suggests: the proposal is intentionally designed to
be minimal, so we can get it in place, get experience using it, then decide
whether any specific syntactic pain point is significant enough to be worth
adding additional sugar/complexity.

As has been mentioned in other threads, the hope is that “beginAsync” is
actually extremely rare in practice. If that is the case, there is little
point to sugaring it.

-Chris

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

First of all, thank you to everyone for reacting ! :)

Taking the messages in chronological order :

Wallacy <wallacyf@gmail.com>
Interesting, its syntax seems to improve the "fire and forget" issue.

@IBAction func buttonClicked() {
  async downloadAndUpdateImageView()
}

While this could be nice it would indeed not be needed in this case @IBAction methods were async as Chris Lattner says.

func SomethingUsingUser() -> Void {
  var user = await getUser() //Only here
  printf(user.age > 21 ? "Let's Drink" : "See you later!")

I don't have a lot of experience with async await syntaxes, but if I understand correctly the proposal and the way async/await works, doing that inside of a non-async function would be problematic as this would block the thread and wouldn't clearly show that calling your function would be blocking (being forced to marked a function as async and the imposed language syntax at call site fixes this issue).
That's why I only proposed "async outside of await" and not "await outside of async", because async outside of await would still enable the compiler to prevent issues like the aforementioned one thanks to a Future like behaviour.

···

=============================================================

Chris Lattner <clattner@nondot.org>

Yes, it is entirely possible that we will want to provide more syntactic sugar than the proposal suggests: the proposal is intentionally designed to be minimal, so we can get it in place, get experience using it, then decide whether any specific syntactic pain point is significant enough to be worth adding additional sugar/complexity.

As has been mentioned in other threads, the hope is that “beginAsync” is actually extremely rare in practice. If that is the case, there is little point to sugaring it.

-Chris

The second part of my proposition is indeed more syntactic sugar if beginAsync ends up being rarely used in practice, but about the first part of my explanation (using async inside of async functions to provide a future like syntax), would it enable to both to drastically reduce the syntactic complexity of async/await and to hide away implementation giving more freedom for future Swift releases as Wallacy and Jonathan Hull suggested?

Thank you ! :)

=============================================================

Wallacy <wallacyf@gmail.com <mailto:wallacyf@gmail.com>>
Using only async/await is pretty easy to learn and teach.
And after that, "Future" can be implement in any way because will not be a
public API anymore (I do not know, but there may also be some opportunities
for optimization as well), and we only need to care about when we need to
"keep the reference" from some async call.

And possibly, they will not need to create any Future type! The variable
type will be "async User" as long as it is not "unwrapped". (
suspend/defer/abandon still possible)

Using async at call site would indeed (in my opinion) make async/await easier to learn (especially given the parallel with optional unwrapping and similarities with other behaviours of Swift, including possible async vars of Actors maybe?).

I'd be interested to know what would be the ramifications of promoting async at type level as you propose, what would be the pros and cons of such an approach ? I'd be interested to get other opinions about it ! :)

In my first idea async at call site would be synthesising a Future<T> just as T? synthesises Optional<T>, but I'd be interested to know too if hiding implementation details would have any advantages for the future of Swift ? Making things more flexible maybe?

=============================================================

Jonathan Hull jhull at gbis.com

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

As for the message of Wallacy I'd be interested the pros and cons of hiding the implementation details ! :)

To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?

  let a = async longCalculationA()
  let b = async longCalculationB() //b doesn’t wait for a to complete before starting
  let c = async longCalculationC() //c doesn’t wait for a or b
  let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

Would this be implemented differently than with Futures? I don't have much experience with concurrency, but I don't see how this would be handled differently than by using Futures, internally ? (at least for this case)

=============================================================

Florent Vilmart florent at flovilmart.com

Probably with:

let a = longCalculationA()
let b = longCalculationB() //b doesn’t wait for a to complete before starting
let c = longCalculationC() //c doesn’t wait for a or b
let (aResult, bResult, cResult) = await Future.collect(a, b, c) //waits until a, b, and c are all available

This isn't possible with the proposed async/await syntax, is it ?

Thank you everyone !! :)

My experience with fire and forget without any control or error detection
is that it looks great in small examples but is inadequate in ‘real’
applications, it is highly deadlock prone! I think the minimum you need is
timeout to break deadlocks, control over the thread running the code,
cancel to eliminate hierarchies of background tasks when the top level is
cancelled (e.g. by user), and status to help debugging.

···

On Sat, 26 Aug 2017 at 7:14 am, Jonathan Hull via swift-evolution < swift-evolution@swift.org> wrote:

I actually *really* like the idea of using ‘async' to start a computation
in a non-blocking way. It is extremely common in real-world code to want
to start a few computations/downloads at once in the background and then
use the results together...

I think full-fledged futures could be a framework thing added on top, but
what I would really love to see at the language level is that using ‘async’
just allows you to defer calling ‘await’. That is, you could get a value
back from something called with async, but you would be forced to await
that value before it could be used:

var image = async downloadImage() //Image is type UIImage
//Do something else here
let size = await image.size //The compiler forces me to call await before
I can actually use the value

This looks somewhat similar to a future, but you can’t interact with it as
a separate type of object. The value above is just a UIImage, but with a
compiler flag/annotation that forces me to call await on it before it can
be accessed/used. The compiler has a lot more freedom to
optimize/reorganize things behind the scenes, because it doesn’t
necessarily need to make an intermediate object.

I don’t think this is just sugar. It adds expressivity and control for a
set of very common use-cases which aren’t fully supported by await alone.

Thanks,
Jon

On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution < > swift-evolution@swift.org> wrote:

Hello Swift community,

I was really interested by the recent* Task-based concurrency manifesto*
and *Concrete proposal for async semantics in Swift.*

Looking at beginAsync() and Futures, I had an idea for a new syntax based
on the `async` keyword, I'd love to hear your feedback about this idea:

https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Thank you ! :)

Trevör
_______________________________________________
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

--
-- Howard.

how would you accomplish the following under the current proposal?

We could implement a Future type (as imagined in the async/await proposal), which would enable something like this:

  let futureA = Future { await longCalculationA() }
  let futureB = Future { await longCalculationB() }
  let futureC = Future { await longCalculationC() }

  // Asynchronously waits for a, b, and c to finish before calling combineCalculations()
  let result = await combineCalculations(a: a.get(), b: b.get(), c: c.get())

If there's no Future type around, it's reasonable to imagine that DispatchQueue.async would be modified to accept an 'async' closure, so you could do this:

  let group = DispatchGroup()
  let queue = DisatchQueue.global()

  var a: Any? = nil
  var b: Any? = nil
  var c: Any? = nil

  group.enter()
  queue.async {
    a = await longCalculationA()
    group.leave()
  }
  
  group.enter()
  queue.async {
    b = await longCalculationB()
    group.leave()
  }

  group.enter()
  queue.async {
    c = await longCalculationC()
    group.leave()
  }

  group.notify {
    combineCalculations(a: a, b: b, c: c)
  }

A Future type certainly makes this look nicer, though.

-BJ

···

On Aug 25, 2017, at 3:49 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:

To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?

  let a = async longCalculationA()
  let b = async longCalculationB() //b doesn’t wait for a to complete before starting
  let c = async longCalculationC() //c doesn’t wait for a or b
  let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

(Note: this is using my version of async below which doesn’t use futures)

Thanks,
Jon

On Aug 25, 2017, at 2:13 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I actually really like the idea of using ‘async' to start a computation in a non-blocking way. It is extremely common in real-world code to want to start a few computations/downloads at once in the background and then use the results together...

I think full-fledged futures could be a framework thing added on top, but what I would really love to see at the language level is that using ‘async’ just allows you to defer calling ‘await’. That is, you could get a value back from something called with async, but you would be forced to await that value before it could be used:

  var image = async downloadImage() //Image is type UIImage
  //Do something else here
  let size = await image.size //The compiler forces me to call await before I can actually use the value

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

I don’t think this is just sugar. It adds expressivity and control for a set of very common use-cases which aren’t fully supported by await alone.

Thanks,
Jon

On Aug 24, 2017, at 4:40 AM, Trevör ANNE DENISE via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello Swift community,

I was really interested by the recent Task-based concurrency manifesto and Concrete proposal for async semantics in Swift.

Looking at beginAsync() and Futures, I had an idea for a new syntax based on the `async` keyword, I'd love to hear your feedback about this idea:
https://github.com/adtrevor/Swift-ideas/blob/master/New%20async%20keyword%20usage.md

Would such a syntax make any sense?

Thank you ! :)

Trevör
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

It looks/behaves very similar to futures, but would potentially be implemented differently. The main difference is that the resulting type is actually the desired type (instead of Future<Type>) with a compiler flag saying that it needs to call await to be used. Behind the scenes, this could be implemented as some sort of future, but the compiler has a lot more freedom to rearrange things to be much more efficient because there is no affordance for the user to introspect or cancel. So for example, it might actually change:

  let image = async downloadImage()
  let size = await image.size

to:

  let size = await downloadImage().size

This would depend on the other code around it, but the compiler has much more freedom to avoid creating intermediate values, or even to create different types of intermediate values which are more efficient for the situation at hand.

Given that as a base, it would be trivial to create a framework offering true Futures (which allow cancelling, etc…)

Thanks,
Jon

···

On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:

=============================================================

Jonathan Hull jhull at gbis.com <http://gbis.com/&gt;

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

As for the message of Wallacy I'd be interested the pros and cons of hiding the implementation details ! :)

To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?

  let a = async longCalculationA()
  let b = async longCalculationB() //b doesn’t wait for a to complete before starting
  let c = async longCalculationC() //c doesn’t wait for a or b
  let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

Would this be implemented differently than with Futures? I don't have much experience with concurrency, but I don't see how this would be handled differently than by using Futures, internally ? (at least for this case)

Probably with:

let a = longCalculationA()
let b = longCalculationB() //b doesn’t wait for a to complete before starting
let c = longCalculationC() //c doesn’t wait for a or b
let (aResult, bResult, cResult) = await Future.collect(a, b, c) //waits until a, b, and c are all available

···

On 25 août 2017 17:48 -0400, wrote:

let a = async longCalculationA()
let b = async longCalculationB() //b doesn’t wait for a to complete before starting
let c = async longCalculationC() //c doesn’t wait for a or b
let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK in JS, any function that returns a promise can be ‘await’ upon, and underneath, to be able to await, a function has to return a promise. Marking a function async in JS, tells the consumer that some await are going on inside, and it’s impossible to use await outside of an async marked function. I believe swift is going that direction too. Futures / Promises are the foundation on which async / await can truly express as it formalizes the boxing of the result types.
What would be interesting is async being based on a protocol FutureType for example, so you can bring your own library and yet, leverage async / await

···

On Aug 25, 2017, 20:50 -0400, Jonathan Hull <jhull@gbis.com>, wrote:

> On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:
>
> =============================================================
> > Jonathan Hull jhull at gbis.com
> > This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.
>
> As for the message of Wallacy I'd be interested the pros and cons of hiding the implementation details ! :)
>
>
> > To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?
> >
> > let a = async longCalculationA()
> > let b = async longCalculationB() //b doesn’t wait for a to complete before starting
> > let c = async longCalculationC() //c doesn’t wait for a or b
> > let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available
>
> Would this be implemented differently than with Futures? I don't have much experience with concurrency, but I don't see how this would be handled differently than by using Futures, internally ? (at least for this case)
>

It looks/behaves very similar to futures, but would potentially be implemented differently. The main difference is that the resulting type is actually the desired type (instead of Future<Type>) with a compiler flag saying that it needs to call await to be used. Behind the scenes, this could be implemented as some sort of future, but the compiler has a lot more freedom to rearrange things to be much more efficient because there is no affordance for the user to introspect or cancel. So for example, it might actually change:

let image = async downloadImage()
let size = await image.size

to:

let size = await downloadImage().size

This would depend on the other code around it, but the compiler has much more freedom to avoid creating intermediate values, or even to create different types of intermediate values which are more efficient for the situation at hand.

Given that as a base, it would be trivial to create a framework offering true Futures (which allow cancelling, etc…)

Thanks,
Jon

Thinking about it, wouldn't hiding the implementation of Future<T> have the advantage of preventing people from returning Futures from functions ?

This would allow to write this:
func foo() async -> Future<SomeType> {
  let futureValue = Future { await someOtherFunc() }
  doSomethingElse()
  return futureValue
}

As this:
func foo() async -> SomeType {
  let futureValue = async someOtherFunc()
  doSomethingElse()
  return futureValue
}

Internally compiler would add an await at return:
func foo() async -> SomeType {
  let futureValue = async someOtherFunc()
  doSomethingElse()
  return await futureValue
}

With this syntax it would seem useless to return Future from a function ! Wouldn't it also avoid to skip some thread safety checks that would be required by Future being publicly implemented as a class ?

What do you think about it ?

I just don't see that async/await adds enough to warrant a language change.
You can write Future on top of GCD and a future type can do more, like
having a cancel, having a timeout, and giving control over what thread is
used.

  -- Howard.

···

On 26 August 2017 at 10:57, Florent Vilmart via swift-evolution < swift-evolution@swift.org> wrote:

Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK in
JS, any function that returns a promise can be ‘await’ upon, and
underneath, to be able to await, a function has to return a promise.
Marking a function async in JS, tells the consumer that some await are
going on inside, and it’s impossible to use await outside of an async
marked function. I believe swift is going that direction too. Futures /
Promises are the foundation on which async / await can truly express as it
formalizes the boxing of the result types.
What would be interesting is async being based on a protocol FutureType
for example, so you can bring your own library and yet, leverage async /
await

On Aug 25, 2017, 20:50 -0400, Jonathan Hull <jhull@gbis.com>, wrote:

On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise < > trevor.annedenise@icloud.com> wrote:

=============================================================

Jonathan Hull jhull at gbis.com

This looks somewhat similar to a future, but you can’t interact with it as
a separate type of object. The value above is just a UIImage, but with a
compiler flag/annotation that forces me to call await on it before it can
be accessed/used. The compiler has a lot more freedom to
optimize/reorganize things behind the scenes, because it doesn’t
necessarily need to make an intermediate object.

As for the message of Wallacy I'd be interested the pros and cons of
hiding the implementation details ! :)

To prove (or potentially disprove) my assertion that this is not just
sugar, how would you accomplish the following under the current proposal?

let a = async longCalculationA()
let b = async longCalculationB() //b doesn’t wait for a to complete before
starting
let c = async longCalculationC() //c doesn’t wait for a or b
let result = await combineCalculations(a: a, b: b, c: c) //waits until a,
b, and c are all available

Would this be implemented differently than with Futures? I don't have much
experience with concurrency, but I don't see how this would be handled
differently than by using Futures, internally ? (at least for this case)

It looks/behaves very similar to futures, but would potentially be
implemented differently. The main difference is that the resulting type is
actually the desired type (instead of Future<Type>) with a compiler flag
saying that it needs to call await to be used. Behind the scenes, this
could be implemented as some sort of future, but the compiler has a lot
more freedom to rearrange things to be much more efficient because there is
no affordance for the user to introspect or cancel. So for example, it
might actually change:

let image = async downloadImage()
let size = await image.size

to:

let size = await downloadImage().size

This would depend on the other code around it, but the compiler has much
more freedom to avoid creating intermediate values, or even to create
different types of intermediate values which are more efficient for the
situation at hand.

Given that as a base, it would be trivial to create a framework offering
true Futures (which allow cancelling, etc…)

Thanks,
Jon

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

Why wouldn’t b wait for a in this example? If it is using futures, those aren’t available in the current proposal.

···

On Aug 25, 2017, at 3:02 PM, Florent Vilmart <florent@flovilmart.com> wrote:

Probably with:

let a = longCalculationA()
let b = longCalculationB() //b doesn’t wait for a to complete before starting
let c = longCalculationC() //c doesn’t wait for a or b
let (aResult, bResult, cResult) = await Future.collect(a, b, c) //waits until a, b, and c are all available

On 25 août 2017 17:48 -0400, wrote:

let a = async longCalculationA()
let b = async longCalculationB() //b doesn’t wait for a to complete before starting
let c = async longCalculationC() //c doesn’t wait for a or b
let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

be doesn't wait if it's defined as

func longCalculationB() async -> SomeType

which would be helpful if it's a long calculation,

in the case it's

func longCalculationB() -> SomeType

That would probably be valid to put the async keyword front even though I would not be a big fan of that as you'd be executing on an indefinite queue a calculation that may not be thread safe.

async would be in that case a wrapper around dispatch_async + semaphore

···

On 25 août 2017 18:08 -0400, Jonathan Hull <jhull@gbis.com>, wrote:

Why wouldn’t b wait for a in this example? If it is using futures, those aren’t available in the current proposal.

> On Aug 25, 2017, at 3:02 PM, Florent Vilmart <florent@flovilmart.com> wrote:
>
> Probably with:
>
> let a = longCalculationA()
> let b = longCalculationB() //b doesn’t wait for a to complete before starting
> let c = longCalculationC() //c doesn’t wait for a or b
> let (aResult, bResult, cResult) = await Future.collect(a, b, c) //waits until a, b, and c are all available
>
> On 25 août 2017 17:48 -0400, wrote:
> >
> > let a = async longCalculationA()
> > let b = async longCalculationB() //b doesn’t wait for a to complete before starting
> > let c = async longCalculationC() //c doesn’t wait for a or b
> > let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

C# had futures (in the form of the Task Parallel Library) before it had async/await. If you could see how much async/await has revolutionized C# programming you would not be making this argument. It is night and day. Asynchronous code is so much clearer with this feature than without. You can write code the is simpler and safer at the same time.

This isn’t an either/or proposition. We should have both, and they should work together.

···

--
Adam Kemp

On Aug 25, 2017, at 10:08 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

I just don't see that async/await adds enough to warrant a language change. You can write Future on top of GCD and a future type can do more, like having a cancel, having a timeout, and giving control over what thread is used.

  -- Howard.

On 26 August 2017 at 10:57, Florent Vilmart via swift-evolution <swift-evolution@swift.org> wrote:
Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK in JS, any function that returns a promise can be ‘await’ upon, and underneath, to be able to await, a function has to return a promise. Marking a function async in JS, tells the consumer that some await are going on inside, and it’s impossible to use await outside of an async marked function. I believe swift is going that direction too. Futures / Promises are the foundation on which async / await can truly express as it formalizes the boxing of the result types.
What would be interesting is async being based on a protocol FutureType for example, so you can bring your own library and yet, leverage async / await

On Aug 25, 2017, 20:50 -0400, Jonathan Hull <jhull@gbis.com>, wrote:

On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:

=============================================================

Jonathan Hull jhull at gbis.com

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

As for the message of Wallacy I'd be interested the pros and cons of hiding the implementation details ! :)

To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?

let a = async longCalculationA()
let b = async longCalculationB() //b doesn’t wait for a to complete before starting
let c = async longCalculationC() //c doesn’t wait for a or b
let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

Would this be implemented differently than with Futures? I don't have much experience with concurrency, but I don't see how this would be handled differently than by using Futures, internally ? (at least for this case)

It looks/behaves very similar to futures, but would potentially be implemented differently. The main difference is that the resulting type is actually the desired type (instead of Future<Type>) with a compiler flag saying that it needs to call await to be used. Behind the scenes, this could be implemented as some sort of future, but the compiler has a lot more freedom to rearrange things to be much more efficient because there is no affordance for the user to introspect or cancel. So for example, it might actually change:

let image = async downloadImage()
let size = await image.size

to:

let size = await downloadImage().size

This would depend on the other code around it, but the compiler has much more freedom to avoid creating intermediate values, or even to create different types of intermediate values which are more efficient for the situation at hand.

Given that as a base, it would be trivial to create a framework offering true Futures (which allow cancelling, etc…)

Thanks,
Jon

_______________________________________________
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

Do you mean async/await as in concurrency proposal or the usage of async at call site?

Trevör

···

Le 26 août 2017 à 07:07, Howard Lovatt <howard.lovatt@gmail.com> a écrit :

I just don't see that async/await adds enough to warrant a language change. You can write Future on top of GCD and a future type can do more, like having a cancel, having a timeout, and giving control over what thread is used.

  -- Howard.

C# had futures (in the form of the Task Parallel Library) before it had async/await. If you could see how much async/await has revolutionized C# programming you would not be making this argument. It is night and day. Asynchronous code is so much clearer with this feature than without. You can write code the is simpler and safer at the same time.

This isn’t an either/or proposition. We should have both, and they should work together.

+1

···

Sent from my iPhone

On 26 Aug 2017, at 18:36, Adam Kemp via swift-evolution <swift-evolution@swift.org> wrote:

--
Adam Kemp

On Aug 25, 2017, at 10:08 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

I just don't see that async/await adds enough to warrant a language change. You can write Future on top of GCD and a future type can do more, like having a cancel, having a timeout, and giving control over what thread is used.

  -- Howard.

On 26 August 2017 at 10:57, Florent Vilmart via swift-evolution <swift-evolution@swift.org> wrote:
Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK in JS, any function that returns a promise can be ‘await’ upon, and underneath, to be able to await, a function has to return a promise. Marking a function async in JS, tells the consumer that some await are going on inside, and it’s impossible to use await outside of an async marked function. I believe swift is going that direction too. Futures / Promises are the foundation on which async / await can truly express as it formalizes the boxing of the result types.
What would be interesting is async being based on a protocol FutureType for example, so you can bring your own library and yet, leverage async / await

On Aug 25, 2017, 20:50 -0400, Jonathan Hull <jhull@gbis.com>, wrote:

On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise <trevor.annedenise@icloud.com> wrote:

=============================================================

Jonathan Hull jhull at gbis.com

This looks somewhat similar to a future, but you can’t interact with it as a separate type of object. The value above is just a UIImage, but with a compiler flag/annotation that forces me to call await on it before it can be accessed/used. The compiler has a lot more freedom to optimize/reorganize things behind the scenes, because it doesn’t necessarily need to make an intermediate object.

As for the message of Wallacy I'd be interested the pros and cons of hiding the implementation details ! :)

To prove (or potentially disprove) my assertion that this is not just sugar, how would you accomplish the following under the current proposal?

let a = async longCalculationA()
let b = async longCalculationB() //b doesn’t wait for a to complete before starting
let c = async longCalculationC() //c doesn’t wait for a or b
let result = await combineCalculations(a: a, b: b, c: c) //waits until a, b, and c are all available

Would this be implemented differently than with Futures? I don't have much experience with concurrency, but I don't see how this would be handled differently than by using Futures, internally ? (at least for this case)

It looks/behaves very similar to futures, but would potentially be implemented differently. The main difference is that the resulting type is actually the desired type (instead of Future<Type>) with a compiler flag saying that it needs to call await to be used. Behind the scenes, this could be implemented as some sort of future, but the compiler has a lot more freedom to rearrange things to be much more efficient because there is no affordance for the user to introspect or cancel. So for example, it might actually change:

let image = async downloadImage()
let size = await image.size

to:

let size = await downloadImage().size

This would depend on the other code around it, but the compiler has much more freedom to avoid creating intermediate values, or even to create different types of intermediate values which are more efficient for the situation at hand.

Given that as a base, it would be trivial to create a framework offering true Futures (which allow cancelling, etc…)

Thanks,
Jon

_______________________________________________
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

Chris's proposal is very explicit about the advantages of the async/await
over the Future/Task, we don't need to rephrase here. The most obvious
advantage of course is because "await" does not block the execution
(Future.get() does).

And the whole proposal about async/await/actors is very, very good!
Except... When talks about the need to implement Future class as part of
the standard library! Like said on async/await proposal, the "Future" needs
another proposal to adress the details. But describ only one "good" feature
of the "Future" over the async/await:

...
"allow parallel execution, by moving await from the call to the result when
it is needed, and wrapping the parallel calls in individual Future objects"
...

This is very important thing! And if not addressed by the language or the
standlibrary, third party libraries will. But also, has few downsides. The
proposal already covered this:

...
"A Future type designed for Swift today would need to be a class, and
therefore need to guard against potentially multithreaded access, races to
fulfill or attempts to fulfill multiple times, and potentially unbounded
queueing of awaiting coroutines on the shared future;"
"The proposed design eliminates the problem of calling an API (without
knowing it is async) and getting a Future<T> back instead of the expected T
result type."
"By encoding async as a first-class part of function types, closure
literals can also be transparently async by contextual type inference. "
"Requiring a future object to be instantiated at every await point adds
overhead."
etc...
...

So... My proposal is: Extend async/await functionality to close the gap
needed to allow parallel execution.

Something like that: (using the same exemple as before)

func downloadUserData() async -> UserData { ... }func downloadImage()
async -> UIImage { ... }
func someAsyncFunc() async -> User {
  var userData = async downloadUserData() // userData is of type `async
UserData` as we used async var image = async downloadImage() // image
is of type `async UserData` return await User(userData, image) //
needs to call await to use any `async T`}

await still does not block execution, the lifetime of `async T` is very
previsible, (Future<T> can be stored, passed around, etc.), and any "Future
Like" type can be implement on the top of this!

async at call side needs to replace beginAsync? Not necessarily. We may
consider that calling anything with 'async' at startup implies beginAsync with
return T and can be 'awaited', suspended, etc. But its not the main use for
async at call side in my opinion. The lifetime of this call can handled in
the same way as beginAsync.

async at call side created another type? No! Its the point here! This
"virtual type" only need to exists on the context of the caller, and can be
used by the compiler to enforce the "await" at some point.

I can "reasync"any call? It's interesting, I think it's worth to be
considered.

func someAsyncFunc() async -> User {
  var userData = async downloadUserData() var image = async
downloadImage() return async User(userData, image) // actually return
() async ->{ await User(userData, image) } or similar.

}

Can i suspend any calls? Maybe in this way:

let imageResource = try async loadWebResource("imagedata.dat")
  do {
    let imageTmp = try await decodeImage(dataResource, imageResource)
  } catch _ as InvalidResourc {
    // Does not need to finish the imageResource await. await
suspendAsync(imageResource) // just a exemple... }catch _ as
CorruptedImage {
    // Give up hope now. await abandon() // like before }

Also, i dont like the idea of suspendAsync be a standlibrary function!
Maybe a keyword modifier? (await suspendAsync _ / await suspendAsync abc )

Anyway... I do not want to be adding too many ideas at the same time, there
are several ideas around "async". My point is just to enable parallel
execution without the introduction of another type. Whatever comes next is
profit!

···

Em sáb, 26 de ago de 2017 às 14:37, Adam Kemp via swift-evolution < swift-evolution@swift.org> escreveu:

C# had futures (in the form of the Task Parallel Library) before it had
async/await. If you could see how much async/await has revolutionized C#
programming you would not be making this argument. It is night and day.
Asynchronous code is so much clearer with this feature than without. You
can write code the is simpler and safer at the same time.

This isn’t an either/or proposition. We should have both, and they should
work together.

--
Adam Kemp

On Aug 25, 2017, at 10:08 PM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

I just don't see that async/await adds enough to warrant a language
change. You can write Future on top of GCD and a future type can do more,
like having a cancel, having a timeout, and giving control over what thread
is used.

  -- Howard.

On 26 August 2017 at 10:57, Florent Vilmart via swift-evolution < > swift-evolution@swift.org> wrote:

Isn’t async / await an evolution over Promises / Tasks / Futures? AFAIK
in JS, any function that returns a promise can be ‘await’ upon, and
underneath, to be able to await, a function has to return a promise.
Marking a function async in JS, tells the consumer that some await are
going on inside, and it’s impossible to use await outside of an async
marked function. I believe swift is going that direction too. Futures /
Promises are the foundation on which async / await can truly express as it
formalizes the boxing of the result types.
What would be interesting is async being based on a protocol FutureType
for example, so you can bring your own library and yet, leverage async /
await

On Aug 25, 2017, 20:50 -0400, Jonathan Hull <jhull@gbis.com>, wrote:

On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise < >> trevor.annedenise@icloud.com> wrote:

=============================================================

Jonathan Hull jhull at gbis.com

This looks somewhat similar to a future, but you can’t interact with it
as a separate type of object. The value above is just a UIImage, but with
a compiler flag/annotation that forces me to call await on it before it can
be accessed/used. The compiler has a lot more freedom to
optimize/reorganize things behind the scenes, because it doesn’t
necessarily need to make an intermediate object.

As for the message of Wallacy I'd be interested the pros and cons of
hiding the implementation details ! :)

To prove (or potentially disprove) my assertion that this is not just
sugar, how would you accomplish the following under the current proposal?

let a = async longCalculationA()
let b = async longCalculationB() //b doesn’t wait for a to complete
before starting
let c = async longCalculationC() //c doesn’t wait for a or b
let result = await combineCalculations(a: a, b: b, c: c) //waits until a,
b, and c are all available

Would this be implemented differently than with Futures? I don't have
much experience with concurrency, but I don't see how this would be handled
differently than by using Futures, internally ? (at least for this case)

It looks/behaves very similar to futures, but would potentially be
implemented differently. The main difference is that the resulting type is
actually the desired type (instead of Future<Type>) with a compiler flag
saying that it needs to call await to be used. Behind the scenes, this
could be implemented as some sort of future, but the compiler has a lot
more freedom to rearrange things to be much more efficient because there is
no affordance for the user to introspect or cancel. So for example, it
might actually change:

let image = async downloadImage()
let size = await image.size

to:

let size = await downloadImage().size

This would depend on the other code around it, but the compiler has much
more freedom to avoid creating intermediate values, or even to create
different types of intermediate values which are more efficient for the
situation at hand.

Given that as a base, it would be trivial to create a framework offering
true Futures (which allow cancelling, etc…)

Thanks,
Jon

_______________________________________________
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