> On Aug 28, 2017, at 11:19 PM, Chris Lattner <clatt...@nondot.org> wrote:
> 
> 
>> On Aug 28, 2017, at 1:09 PM, Adam Kemp via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> I decided to split this out to its own thread because it seems orthogonal to 
>> other issues being discussed.
>> 
>> When I read this line from the proposal:
>> 
>> await decodeImage(dataResource.get(), imageResource.get())
>> 
>> It’s not clear to me where the asynchronous call is. There are three 
>> function calls on that line. Which ones might actually suspend? You can’t 
>> tell by looking at it because there’s only one await keyword (the answer is 
>> all 3).
> 
> Yes, this is a reasonable concern.  We debated it heavily in the Swift 2 
> timeframe when introducing error handling (as other’s have pointed out, it 
> works the same way).
> 
> This is a tradeoff between the readability benefits of marking non-obvious 
> control flow vs the readability disadvantage of having noise in the code. 
> Requiring marking on every async or throwing call is particularly bad in the 
> case of chaining.  Compare:
> 
>    let x = try (try (try a.foo()).bar()).baz()
> vs:
>    let x = try a.foo().bar().baz()
> 
> In the Swift 2 timeframe, we decided that in many cases, it is mostly obvious 
> what APIs can throw, so one marker is enough.  That said, there ARE 
> potentially confusing cases, and some programmers may want to be more 
> explicit about marking.  This is why the compiler allows you to explicitly 
> mark subexpressions if you’d like.
> 
> I believe that this design has served the community well, and I haven’t heard 
> of serious problems with it.  I’m pretty confident that async following the 
> same model will have similar success.
> 
> -Chris
> 

I think that decision makes sense for try/throws, but I feel like the await 
keyword is fundamentally different from that. The pitfalls of not understanding 
how the code is transformed and how it will behave at runtime are much greater 
with await than with try.

If you have a line of code with multiple expressions that can throw then the 
consequences of not knowing which particular one threw the error are minor. In 
most cases it doesn’t matter, and you would handle a given error the same 
regardless of which subexpression threw the error.

With await the function is actually broken up into pieces, and unrelated code 
can run in between those pieces on the same thread and/or the same queue. That 
has a much higher potential of leading to subtle bugs if you can’t see where 
those breaks are.

That’s why I think that it is important for every one of those locations to be 
explicitly marked so that it is very clear where the breaks in the function 
are, and thus where other code can run.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to