> 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