Okay, that's an interesting proposal. I'm not qualified to judge how big of a 
win the compiler optimizations would be there; I'm a little skeptical, but I 
admit a lack of expertise there. It seems like it's not essential to the core 
'async/await' proposal, though; it could be added later with no source 
breakage, and in the meantime we can accomplish most of the same behavior 
through an explicit Future type. I think it makes more sense to consider the 
base proposal before adding more complexity to it.

-BJ

> On Sep 3, 2017, at 10:15 PM, Jonathan Hull <[email protected]> wrote:
> 
> 
>> On Sep 3, 2017, at 7:35 PM, BJ Homer <[email protected]> wrote:
>> 
>> Jonathan,
>> 
>> You've mentioned the desire to have 'async' defer calling 'await', but I 
>> haven't seen a detailed design yet.
> Oh, we discussed it awhile back on a few other threads.  I am happy to help 
> write up a more formal/detailed design if there is enough interest...
> 
>> For example, is the following code valid?
>> 
>>   let image = async fetchImage()
>>   let image2 = async fetchImage()
>>   let deferredThings = [image1, image2]
>> 
>> If so, what is the type of 'deferredThings'? And how does it not count as 
>> 'using' the values.
> 
> No this code is not valid.  You would need to ‘await’ both image 1 & 2 before 
> they could be put in an array or transferred to another variable. You could 
> combine the ‘await’s though (similar to try):
> 
>       let image = async fetchImage()
>       let image2 = async fetchImage()
>       let deferredThings = await [image1, image2]
> 
> 
> Note: You can return something which is deferred from an async function 
> without awaiting though...
> 
> 
>> If the above code is not valid, how is this situation better than the 
>> suggested use of a Future type to allow concurrent async requests?
>> 
>>   let future1 = Future { await fetchImage() }
>>   let future2 = Future { await fetchImage() }
>>   let deferredThings = [future1, future2]
>> 
>> Note that in this example, 'deferredThings' has a concrete type, and we can 
>> inspect its values.
> 
> It isn’t meant to be used instead of Futures (though you may not need to 
> reach for them as often), it is a much lower-level construct which would be 
> used as a building block for things like futures (and other concurrency 
> constructs).
> 
> Because there is no way for the programmer to get at the thing being 
> ‘await’ed (or any representation of it) without awaiting on it, and it can’t 
> escape the context, it gives the compiler some extra guarantees that it can 
> use to optimize things behind the scenes. Even if the compiler just ends up 
> creating a future behind the scenes, that implementation is completely hidden 
> to the programmer, and can be updated/changed at any time by the compiler 
> team without involving evolution.
> 
> Let’s say at some point down the road as part of the actor work, the compiler 
> ends up getting some visibility into how actor queues will be coalesced… Then 
> it can use that knowledge to reorganize the code above to be more efficient.  
> For example, if it knows that the part of the calls to fetchImage() will be 
> serialized by an actor, it can just make that part synchronous and avoid the 
> asynchronous overhead.  If we had baked in everything at the low-level to use 
> future objects, we wouldn’t be able to make that optimization.
> 
> There are 2 big results from this:
> 
> 1) It gives us the ability to easily start several things behind the scenes 
> and then await the group of them finishing
> 
> 2) Our implementation of Futures (and other constructs) can potentially take 
> advantage of the compiler optimizations by using this beneath the hood.
> 
> 
> The first point is huge for me. This is an extremely common thing to want in 
> real-world code, but it usually requires a bunch of complex (sometimes 
> error-prone) machinery to actually pull off. There is often wasted overhead 
> as well.  I like that I can do it here in a very natural and lightweight way. 
>  (Futures also simplify this problem a great deal, but I wouldn’t really call 
> them lightweight). 
> 
> 
>> You keep bringing up this suggestion, so I must be missing something, but it 
>> seems to me that your suggestion is covered by Futures. Why is calling with 
>> 'async' better?
> 
> As I said above, I think this will help our Futures be much more efficient 
> when we build them, but there are also some advantages of having this as an 
> option and not just using Futures for everything.
> 
> Mainly, futures require a different return type, and they require 
> boxing/unboxing.  To chain futures, each link in the chain has to be 
> future-aware… and each link can only be used with futures (i.e. the return 
> type is Future<MyType>).  There are a lot of cases where I am boxing just to 
> unbox and re-box.  Most of that is fine as long as the framework was built 
> with it in mind, but it doesn’t work as well if I want to add the 
> functionality post-hoc.
> 
> With ‘async’ being used to defer ‘await’, it just works on any function which 
> can be awaited.  Further, it can be chained naturally through any number of 
> async functions.  I showed this in another thread, but if you think through 
> what happens when you return something which still needs to be awaited, you 
> see that that state is naturally passed along with it (the function was 
> either called with ‘await’ or ‘async’, and thus the return value is either 
> awaited on, or the result picks up the compiler marking from ‘async’ showing 
> it still needs to be awaited).  Because there is no (visible) boxing, you 
> don’t have to worry about monads, etc…
> 
> It basically nests in the same way that try/throws nests, and we already have 
> to do that for async/await anyway… so it is a lot of win for very little 
> additional complexity (at least on the usage side).
> 
> Thanks,
> Jon
> 
> 
> 
>> -BJ
>> 
>>> On Sep 3, 2017, at 6:01 PM, Jonathan Hull via swift-evolution 
>>> <[email protected]> wrote:
>>> 
>>> 
>>>>> On Sep 3, 2017, at 9:04 AM, Chris Lattner via swift-evolution 
>>>>> <[email protected]> wrote:
>>>>>> On Sep 3, 2017, at 4:00 AM, David Hart <[email protected]> wrote:
>>>>>> Please don’t read too much into the beginAsync API.  It is merely a 
>>>>>> strawman, and intended to be a low-level API that higher level 
>>>>>> abstractions (like a decent futures API) can be built on top of.  I 
>>>>>> think it is important to have some sort of primitive low-level API that 
>>>>>> is independent of higher level abstractions like Futures.
>>>>>> 
>>>>>> This is all a way of saying “yes, having something like you propose 
>>>>>> makes sense” but that it should be part of the Futures API, which is 
>>>>>> outside the scope of the async/await proposal.
>>>>> 
>>>>> But it would be nice for all high-level APIs that conform to a Awaitable 
>>>>> protocol to be used with await without having to reach for a get property 
>>>>> or something similar everytime.
>>>> 
>>>> The futures API that is outlined in the proposal is just an example, it 
>>>> isn’t a concrete pitch for a specific API.  There are a bunch of 
>>>> improvements that can (and should) be made to it, it is just that a 
>>>> futures API should be the subject of a follow-on proposal to the basic 
>>>> async/await mechanics.
>>> 
>>> Would it be possible to have the manifesto be a series of proposals then?  
>>> I really think it is important for us to look at how all of these things 
>>> fit together.  I agree that async/await should come first, but looking at 
>>> how concrete things like Futures would work may help to inform the design 
>>> of async/await.  We should do the back-propigation in our design before 
>>> anything is locked in...
>>> 
>>> The thing I would most like to see as a quick follow-on to async/await is 
>>> the ability to use the ‘async’ keyword to defer ‘await’. This feels very 
>>> natural, is highly optimizable by the compiler, and it allows for a lot of 
>>> very common use-cases which are not covered well by pure async/await.  I 
>>> think it would have a large impact on the eventual design/implementation of 
>>> futures (and at least some impact on the design of async/await).
>>> 
>>> Thanks,
>>> Jon
>>> _______________________________________________
>>> 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