> On 28 Aug 2017, at 23:14, Jean-Daniel via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> 
>> Le 28 août 2017 à 06:14, Howard Lovatt via swift-evolution 
>> <swift-evolution@swift.org> a écrit :
>> 
>> One of the biggest incumbents in this space on the server side is Java and 
>> its concurrency is based on futures and works very well (though there are a 
>> lot of libraries built on top of basic futures). 
> 
> Most server side libraries don’t use Java Future as they force blocking at 
> some point to get the future result. They instead have there own 
> implementation that provide async completion handler (ListenableFuture, …), 
> which result in the pattern we are trying to avoid with coroutine and 
> async/await.  This is not a very good example.

JavaScript Promise + async/await and C# Task + async/await are good example 
though.

>>> On 28 August 2017 at 12:35, Florent Vilmart <flor...@flovilmart.com> wrote:
>>> Adam, you’re completely right, languages as c# and JS have been through the 
>>> path before, (callback, Promises , async/await) I believe Chris’s goal it 
>>> to avoid building a promise implementation and go straight to a coroutines 
>>> model, which is more deeply integrated with the compiler. I don’t see a 
>>> particular trade off, pursuing that route, and the main benefit is that 
>>> coroutines can power any asynchronous metaphor (Signals, Streams, Futures, 
>>> Promises etc...) which is not true of Futures so i would tend to think that 
>>> for the long run, and to maximize usability, async/await/yield would 
>>> probably be the way to go.
>>> 
>>>> On Aug 27, 2017, 22:22 -0400, Adam Kemp <adam.k...@apple.com>, wrote:
>>>> As has been explained, futures can be built on top of async/await (or the 
>>>> other way around). You can have the best of both worlds. We are not losing 
>>>> anything by having this feature. It would be a huge improvement to have 
>>>> this as an option. 
>>>> 
>>>> However, using futures correctly requires more nested closures than you 
>>>> have shown in your examples to avoid blocking any threads. That's why 
>>>> you're not seeing the advantage to async/await. You're comparing examples 
>>>> that have very different behaviors.
>>>> 
>>>> That said, I have also expressed my opinion that it is better to build 
>>>> async/await on top of futures rather than the other way around. I believe 
>>>> it is more powerful and cleaner to make async/await work with any 
>>>> arbitrary future type (via a protocol). The alternative (building futures 
>>>> on top of async/await) requires more code when the two are mixed. I very 
>>>> much prefer how it's done in C#, where you can freely mix the two models 
>>>> without having to resort to ad-hoc wrappers, and you can use async/await 
>>>> with any futures implementation you might already be using.
>>>> 
>>>> I really think we should be having more discussion about the tradeoffs 
>>>> between those two approaches, and I'm concerned that some of the opinions 
>>>> about how C# does it are not based on a clear and accurate understanding 
>>>> of how it actually works in that language. 
>>>> 
>>>> --
>>>> Adam Kemp
>>>> 
>>>> On Aug 27, 2017, at 6:02 PM, Howard Lovatt <howard.lov...@gmail.com> wrote:
>>>> 
>>>>> The async/await is very similar to the proposed Future (as I posed 
>>>>> earlier) with regard to completion-handler code, they both re-write the 
>>>>> imported completion-handler function using a closure, the relevant 
>>>>> sentence from the Async Proposal is:
>>>>> 
>>>>> "Under the hood, the compiler rewrites this code using nested closures 
>>>>> ..."
>>>>> 
>>>>> Unlike the proposed future code the async code is not naturally parallel, 
>>>>> in the running example the following lines from the async code are run in 
>>>>> series, i.e. await blocks:
>>>>> 
>>>>>   let dataResource  = await loadWebResource("dataprofile.txt")
>>>>>   let imageResource = await loadWebResource("imagedata.dat")
>>>>> The equivalent lines using the proposed Future:
>>>>>   let dataResource  = loadWebResource("dataprofile.txt")
>>>>>   let imageResource = loadWebResource("imagedata.dat")
>>>>> Run in parallel and therefore are potentially faster assuming that 
>>>>> resources, like cores and IO, are available.
>>>>> 
>>>>> Therefore you would be better using a Future than an async, so why 
>>>>> provide an async unless you can make a convincing argument that it allows 
>>>>> you to write a better future?
>>>>> 
>>>>>   -- Howard.
>>>>> 
>>>>>> On 28 August 2017 at 09:59, Adam Kemp <adam.k...@apple.com> wrote:
>>>>>> This example still has nested closures (to create a Future), and still 
>>>>>> relies on a synchronous get method that will block a thread. Async/await 
>>>>>> does not require blocking any threads.
>>>>>> 
>>>>>> I’m definitely a fan of futures, but this example isn’t even a good 
>>>>>> example of using futures. If you’re using a synchronous get method then 
>>>>>> you’re not using futures properly. They’re supposed to make it easy to 
>>>>>> avoid writing blocking code. This example just does the blocking call on 
>>>>>> some other thread.
>>>>>> 
>>>>>> Doing it properly would show the benefits of async/await because it 
>>>>>> would require more nesting and more complex error handling. By 
>>>>>> simplifying the code you’ve made a comparison between proper 
>>>>>> asynchronous code (with async/await) and improper asynchronous code 
>>>>>> (your example).
>>>>>> 
>>>>>> That tendency to want to just block a thread to make it easier is 
>>>>>> exactly why async/await is so valuable. You get simple code while still 
>>>>>> doing it correctly. 
>>>>>> 
>>>>>> --
>>>>>> Adam Kemp
>>>>>> 
>>>>>> On Aug 27, 2017, at 4:00 PM, Howard Lovatt via swift-evolution 
>>>>>> <swift-evolution@swift.org> wrote:
>>>>>> 
>>>>>>> The running example used in the white paper coded using a Future is:
>>>>>>> 
>>>>>>> func processImageData1() -> Future<Image> {
>>>>>>>     return AsynchronousFuture { _ -> Image in
>>>>>>>         let dataResource  = loadWebResource("dataprofile.txt") // 
>>>>>>> dataResource and imageResource run in parallel.
>>>>>>>         let imageResource = loadWebResource("imagedata.dat")
>>>>>>>         let imageTmp      = decodeImage(dataResource.get ?? 
>>>>>>> Resource(path: "Default data resource or prompt user"), 
>>>>>>> imageResource.get ?? Resource(path: "Default image resource or prompt 
>>>>>>> user"))
>>>>>>>         let imageResult   =  dewarpAndCleanupImage(imageTmp.get ?? 
>>>>>>> Image(dataPath: "Default image or prompt user", imagePath: "Default 
>>>>>>> image or prompt user"))
>>>>>>>         return imageResult.get ?? Image(dataPath: "Default image or 
>>>>>>> prompt user", imagePath: "Default image or prompt user")
>>>>>>>     }
>>>>>>> }
>>>>>>> 
>>>>>>> This also avoids the pyramid of doom; the pyramid is avoided by 
>>>>>>> converting continuation-handlers into either a sync or future, i.e. it 
>>>>>>> is the importer that eliminates the nesting by translating the code 
>>>>>>> automatically. 
>>>>>>> 
>>>>>>> This example using Future also demonstrates three advantages of Future: 
>>>>>>> they are naturally parallel (dataResource and imageResource lines run 
>>>>>>> in parallel), they timeout automatically (get returns nil if the Future 
>>>>>>> has taken too long), and if there is a failure (for any reason 
>>>>>>> including timeout) it provides a method of either detecting the failure 
>>>>>>> or providing a default (get returns nil on failure). 
>>>>>>> 
>>>>>>> There are a three of other advantages a Future has that this example 
>>>>>>> doesn’t show: control over which thread the Future runs on, Futures can 
>>>>>>> be cancelled, and debugging information is available.
>>>>>>> 
>>>>>>> You could imagine `async` as a syntax sugar for Future, e.g. the above 
>>>>>>> Future example could be:
>>>>>>> 
>>>>>>> func processImageData1() async -> Image {
>>>>>>>     let dataResource  = loadWebResource("dataprofile.txt") // 
>>>>>>> dataResource and imageResource run in parallel.
>>>>>>>     let imageResource = loadWebResource("imagedata.dat")
>>>>>>>     let imageTmp      = decodeImage(dataResource.get ?? Resource(path: 
>>>>>>> "Default data resource or prompt user"), imageResource.get ?? 
>>>>>>> Resource(path: "Default image resource or prompt user"))
>>>>>>>     let imageResult   =  dewarpAndCleanupImage(imageTmp.get ?? 
>>>>>>> Image(dataPath: "Default image or prompt user", imagePath: "Default 
>>>>>>> image or prompt user"))
>>>>>>>     return imageResult.get ?? Image(dataPath: "Default image or prompt 
>>>>>>> user", imagePath: "Default image or prompt user")
>>>>>>> }
>>>>>>> 
>>>>>>> Since an async is sugar for Future the async runs as soon as it is 
>>>>>>> created (as soon as the underlying Future is created) and get returns 
>>>>>>> an optional (also cancel and status would be still be present). Then if 
>>>>>>> you want control over threads and timeout they could be arguments to 
>>>>>>> async:
>>>>>>> 
>>>>>>> func processImageData1() async(queue: DispatchQueue.main, timeout: 
>>>>>>> .seconds(5)) -> Image { ... }
>>>>>>> 
>>>>>>>> On Sat, 26 Aug 2017 at 11:00 pm, Florent Vilmart 
>>>>>>>> <flor...@flovilmart.com> wrote:
>>>>>>>> Howard, with async / await, the code is flat and you don’t have to 
>>>>>>>> unowned/weak self to prevent hideous cycles in the callbacks.
>>>>>>>> Futures can’t do that
>>>>>>>> 
>>>>>>>>> On Aug 26, 2017, 04:37 -0400, Goffredo Marocchi via swift-evolution 
>>>>>>>>> <swift-evolution@swift.org>, wrote:
>>>>>>>>> With both he now built in promises in Node8 as well as libraries like 
>>>>>>>>> Bluebird there was ample time to evaluate them and convert/auto 
>>>>>>>>> convert at times libraries that loved callback pyramids of doom when 
>>>>>>>>> the flow grows complex into promise based chains. Converting to 
>>>>>>>>> Promises seems magical for the simple case, but can quickly descend 
>>>>>>>>> in hard to follow flows and hard to debug errors when you move to non 
>>>>>>>>> trivial multi path scenarios. JS is now solving it with their 
>>>>>>>>> implementation of async/await, but the point is that without the full 
>>>>>>>>> picture any single solution would break horribly in real life 
>>>>>>>>> scenarios.
>>>>>>>>> 
>>>>>>>>> Sent from my iPhone
>>>>>>>>> 
>>>>>>>>> On 26 Aug 2017, at 06:27, Howard Lovatt via swift-evolution 
>>>>>>>>> <swift-evolution@swift.org> wrote:
>>>>>>>>> 
>>>>>>>>>> My argument goes like this:
>>>>>>>>>> 
>>>>>>>>>>   1. You don't need async/await to write a powerful future type; you 
>>>>>>>>>> can use the underlying threads just as well, i.e. future with 
>>>>>>>>>> async/await is no better than future without. 
>>>>>>>>>> 
>>>>>>>>>>   2. Since future is more powerful, thread control, cancel, and 
>>>>>>>>>> timeout, people should be encouraged to use this; instead because 
>>>>>>>>>> async/await are language features they will be presumed, 
>>>>>>>>>> incorrectly, to be the best way, consequently people will get into 
>>>>>>>>>> trouble with deadlocks because they don't have control.
>>>>>>>>>> 
>>>>>>>>>>   3. async/await will require some engineering work and will at best 
>>>>>>>>>> make a mild syntax improvement and at worst lead to deadlocks, 
>>>>>>>>>> therefore they just don't carry their weight in terms of useful 
>>>>>>>>>> additions to Swift.
>>>>>>>>>> 
>>>>>>>>>> Therefore, save some engineering effort and just provide a future 
>>>>>>>>>> library.
>>>>>>>>>> 
>>>>>>>>>> To turn the question round another way, in two forms:
>>>>>>>>>> 
>>>>>>>>>>   1. What can async/wait do that a future can't?
>>>>>>>>>> 
>>>>>>>>>>   2. How will future be improved if async/await is added?
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>   -- Howard.
>>>>>>>>>> 
>>>>>>>>>>> On 26 August 2017 at 02:23, Joe Groff <jgr...@apple.com> wrote:
>>>>>>>>>>> 
>>>>>>>>>>>> On Aug 25, 2017, at 12:34 AM, Howard Lovatt 
>>>>>>>>>>>> <howard.lov...@gmail.com> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>>  In particular a future that is cancellable is more powerful that 
>>>>>>>>>>>> the proposed async/await.
>>>>>>>>>>> 
>>>>>>>>>>> It's not more powerful; the features are to some degree disjoint. 
>>>>>>>>>>> You can build a Future abstraction and then use async/await to 
>>>>>>>>>>> sugar code that threads computation through futures. Getting back 
>>>>>>>>>>> to Jakob's example, someone (maybe the Clang importer, maybe 
>>>>>>>>>>> Apple's framework developers in an overlay) will still need to 
>>>>>>>>>>> build infrastructure on top of IBActions and other currently ad-hoc 
>>>>>>>>>>> signalling mechanisms to integrate them into a more expressive 
>>>>>>>>>>> coordination framework.
>>>>>>>>>>> 
>>>>>>>>>>> -Joe
>>>>>>>>>> 
>>>>>>>>>> _______________________________________________
>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>> swift-evolution@swift.org
>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> 
>>>>>>> --
>>>>>>> -- Howard.
>>>>>>> _______________________________________________
>>>>>>> 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
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to