> 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