> Am 27.08.2017 um 17:48 schrieb David Hart via swift-evolution 
> <[email protected]>:
> 
> 
>> On 27 Aug 2017, at 06:09, Wallacy via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> 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:
> 
> I agree that having a way to “await multiple async results at the same time” 
> seems like something very important. And both JavaScript and C# get those 
> because async/await is based on Futures/Promises. I’m okay with the current 
> direction of the async/await proposal in Swift (i.e., not built on top of 
> Promises), but we need to a way to be on feature parity with those other 
> languages (without a third-party library) if we want Swift’s async/await to 
> be truly useful.


I like the `Futureless` async/await proposal too and think that using `async` 
in two different ways as proposed by some could be confusing.

I think providing some simple `combinators` atop of coroutine based async/await 
would be very versatile:

e.g providing a `parallel` combinator would allow to `await` multiple async 
tasks:

```
let (userData, image) = await parallel(
                                        await downloadUserData(),
                                        await downloadImage()
                                     )
```

`parallel()` could work like this:

```
func parallel<T, U>(_ t: @autoclosure () async throws -> T, _ u: @autoclosure 
() async throws -> U) async rethrows -> (T, U) {
        // implementation left as an exercise ;-)
}

The method could also take some additional parameters to allow specification of 
timeouts etc.

You could also define some infix operators (like `<||>`) so that above would 
become even simpler:

```
let (userData, image) = await downloadUserData() <||> await downloadImage()
```

> 
>> ...
>> "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 
>> <[email protected] <mailto:[email protected]>> 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 
>> <[email protected] <mailto:[email protected]>> 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 
>>> <[email protected] <mailto:[email protected]>> 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 <[email protected] 
>>> <mailto:[email protected]>>, wrote:
>>>> 
>>>>> On Aug 25, 2017, at 3:38 PM, Trevör Anne Denise 
>>>>> <[email protected] <mailto:[email protected]>> 
>>>>> wrote:
>>>>> 
>>>>> =============================================================
>>>>>> Jonathan Hull jhull at gbis.com <http://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
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to