> On 29 Aug 2017, at 02:22, Xiaodi Wu via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> On Mon, Aug 28, 2017 at 16:10 Adam Kemp via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> I know what the proposal said. I’m making a case that there is value in doing 
> it differently.
> 
> The composability of futures is valuable. Mixing and matching async/await 
> with futures is also valuable. The queue-returning behavior that you can get 
> from futures is also valuable, and building async/await on top of futures 
> means async/await can get that for free.
> 
> Why couldn't you mix and match async/await and futures and get the 
> queue-return behavior of futures if futures are built on top of async/await 
> instead off the other way around?

We could, but the syntax is much worse. Contrast:

async/await built on top of Futures

let image = preprocessImage(downloadImage())
let text = translate(downloadText())
await render(image: image, text: text)

Futures built on top of async/await

let image = Future(downloadImage).then({ preprocessImage($0) })
let text = Future(downloadText).then({ translate($0) })
await render(image: image.get(), text: text.get())

> Maybe you don’t value those things, which is fine. But I do, and maybe other 
> people do too. That’s why we’re having a discussion about it.
> 
> It can also be valuable having a minimal implementation, but we have to 
> acknowledge that it comes with a downside as well. The problem with doing a 
> minimal implementation is that you can be stuck with the consequences for a 
> long time. I want to make sure that we’re not stuck with the consequences of 
> a minimal implementation that doesn’t adequately address the problems that 
> async/await should be addressing. I’d hate for Swift to get an async/await 
> that is so weak that it has to be augmented by tedious boilerplate code 
> before it’s useful.
> 
> 
>> On Aug 28, 2017, at 1:54 PM, Wallacy <walla...@gmail.com 
>> <mailto:walla...@gmail.com>> wrote:
>> 
>> We don't need to this now!
>> 
>> Again: (Using proposal words)
>> 
>> "It is important to understand that this is proposing compiler support that 
>> is completely concurrency runtime-agnostic. This proposal does not include a 
>> new runtime model (like "actors") - it works just as well with GCD as with 
>> pthreads or another API. Furthermore, unlike designs in other languages, it 
>> is independent of specific coordination mechanisms, such as futures or 
>> channels, allowing these to be built as library feature"
>> 
>> and
>> 
>> "This proposal does not formally propose a Future type, or any other 
>> coordination abstractions. There are many rational designs for futures, and 
>> a lot of experience working with them. On the other hand, there are also 
>> completely different coordination primitives that can be used with this 
>> coroutine design, and incorporating them into this proposal only makes it 
>> larger."
>> 
>> and
>> 
>> We focus on task-based concurrency abstractions commonly encountered in 
>> client and server applications, particularly those that are highly event 
>> driven (e.g. responding to UI events or requests from clients). This does 
>> not attempt to be a comprehensive survey of all possible options, nor does 
>> it attempt to solve all possible problems in the space of concurrency. 
>> Instead, it outlines a single coherent design thread that can be built over 
>> the span of years to incrementally drive Swift to further greatness. 
>> 
>> and
>> 
>> This proposal has been kept intentionally minimal, but there are many 
>> possible ways to expand this in the future.
>> 
>> ....
>> 
>> The point is: No Future type is indeed proposed yet!
>> 
>> The proposal try to include de "minimum" required to implement a basic 
>> async/await to solve the problem created by the GCD! (Pyramid of doom)
>> 
>> The question is: How do you do the same using dispatch_async ? 
>> dispatch_async also does not return nothing to do what you are intentend do 
>> do!
>> 
>> Algo, by Swift 5 manifesto, there's no compromise to make a "complete" 
>> concurrency model by this time!
>> 
>> My intention is only make parity to dispatch_async, but also make the ground 
>> free to make more complex implementation like Futures in another round on 
>> top of this one.
>> 
>> This 'async T' can be a real type in the future? Maybe will... But doesn't 
>> matter now! Now we only need to is some kind of type which need to be 
>> unwrapped using await before use. Maybe this intermediary/virtual type can 
>> be a real thing and gain some abilities at some point! Maybe a full Future 
>> type, why not?
>> 
>> Em seg, 28 de ago de 2017 às 17:33, Adam Kemp <adam.k...@apple.com 
>> <mailto:adam.k...@apple.com>> escreveu:
>> How would these anonymous types get composed? If I wanted to implement a 
>> function that takes a collection of futures and wait on it, how would I do 
>> that? That is, how would I implement the equivalent of C#’s Task.WhenAll and 
>> Task.WhenAny methods?
>> 
>> More generally, how do you pass one of these typeless futures to some other 
>> function so that we can do the waiting there?
>> 
>> 
>>> On Aug 28, 2017, at 1:23 PM, Wallacy <walla...@gmail.com 
>>> <mailto:walla...@gmail.com>> wrote:
>>> 
>>> And that's why I (and others) are suggesting:
>>> 
>>> func processImageData1a() async -> Image {
>>>   let dataResource  = async loadWebResource("dataprofile.txt") // No future 
>>> type here... Just another way to call dispatch_async under the hood.
>>>   let imageResource = async loadWebResource("imagedata.dat")
>>>   
>>>   // ... other stuff can go here to cover load latency...
>>>   
>>>   let imageTmp    = await decodeImage(dataResource, imageResource) // 
>>> Compiles force await call here...
>>>   let imageResult = await dewarpAndCleanupImage(imageTmp)
>>>   return imageResult
>>> }
>>> 
>>> And now we gain all advantages of async/await again without to handle with 
>>> one more type.
>>> 
>>> Em seg, 28 de ago de 2017 às 17:07, Adam Kemp via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> escreveu:
>>> I think the biggest tradeoff is clearer when you look at the examples from 
>>> the proposal where futures are built on top of async/await:
>>> 
>>> func processImageData1a() async -> Image {
>>>   let dataResource  = Future { await loadWebResource("dataprofile.txt") }
>>>   let imageResource = Future { await loadWebResource("imagedata.dat") }
>>>   
>>>   // ... other stuff can go here to cover load latency...
>>>   
>>>   let imageTmp    = await decodeImage(dataResource.get(), 
>>> imageResource.get())
>>>   let imageResult = await dewarpAndCleanupImage(imageTmp)
>>>   return imageResult
>>> }
>>> 
>>> With this approach you have to wrap each call site to create a future. 
>>> Compare to this:
>>> 
>>> func processImageData1a() -> Future<Image> {
>>>   let dataResourceFuture  = loadWebResource("dataprofile.txt”);
>>>   let imageResourceFuture = loadWebResource("imagedata.dat”);
>>>   
>>>   // ... other stuff can go here to cover load latency...
>>>   
>>>   let imageTmp    = await decodeImage(await dataResourceFuture, await 
>>> imageResourceFuture)
>>>   let imageResult = await dewarpAndCleanupImage(imageTmp)
>>>   return imageResult
>>> }
>>> 
>>> Here, not only are the explicit wrappers gone, but this function itself can 
>>> be used with either await or as a future. You get both options with one 
>>> implementation.
>>> 
>>> As I’ve mentioned before, C#’s implementation is not tied to any one 
>>> particular futures implementation. The Task type is commonly used, but 
>>> async/await does not directly depend on Task. Instead it works with any 
>>> return type that meets certain requirements (detailed here: 
>>> https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/ 
>>> <https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/>). 
>>> Swift could do this using a protocol, which can be retroactively applied 
>>> using an extension.
>>> 
>>> Obviously for this to be useful we would need some kind of existing future 
>>> implementation, but at least we wouldn’t be tied to any particular one. 
>>> That would mean library maintainers who have already been using their own 
>>> futures implementations could quickly adopt async/await in their code 
>>> without having to rewrite their futures library or throw wrappers around 
>>> every usage of async/await. They could just adopt a protocol (using an 
>>> extension, even) and get async/await support for free.
>>> 
>>> The downside is that this feature would be specific to the async/await use 
>>> case rather than a generic coroutine implementation (i.e., there would have 
>>> to be a separate compiler transform for yield return). It’s not clear to me 
>>> why it should be a goal to have just one generic coroutine feature. The 
>>> real-world usages of async/await and yield return are different enough that 
>>> I’m not convinced we could have a single compiler feature that meets the 
>>> needs of both cleanly.
>>> 
>>>> On Aug 27, 2017, at 7:35 PM, Florent Vilmart <flor...@flovilmart.com 
>>>> <mailto: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 
>>>> <mailto: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 
>>>>> <mailto: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 
>>>>>> <mailto: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 <mailto: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 <mailto: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 <mailto: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 <mailto: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 
>>>>>>>>> <mailto:jgr...@apple.com>> wrote:
>>>>>>>>> 
>>>>>>>>>> On Aug 25, 2017, at 12:34 AM, Howard Lovatt <howard.lov...@gmail.com 
>>>>>>>>>> <mailto: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 <mailto:swift-evolution@swift.org>
>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>> 
>>>>>>> --
>>>>>>> -- Howard.
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>> <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 
>>> <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 
> <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