<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I don't believe that having "await" everywhere will remind you that you have to precalculate and cache operands to suspending operations. In fact, it sounds like your goal is not to enforce that every async operation is gated behind `await`, but to ensure that developers cache the operands of asynchronous operations if they need to do it. IMO, you're choosing the wrong tool for this. `Await` goes on the operation, not on the operands; but it's the operands that you're trying to protect. This example has one `await` per asynchronous operation but it still exhibits the problem that you're hoping to solve:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">let webProfile = await loadWebResource(self.webProfilePath)<br class="">let image = await loadWebResource(self.imagePath)<br class="">await decodeImage(webProfile, image)</blockquote><br class=""></div><div class="">This code doesn't feel any more wrong than your single statement with three asynchronous operations, and to me that means that your proposed solution is insufficient to address the problem that you describe (if there's a problem at all).</div><div class=""><br class=""></div><div class="">Additionally, in the majority of cases, `await`ing at every async expression will be just noise. For instance, `await foo(await bar())` can't possibly exhibit the problem that you describe because bar() is guaranteed to complete before foo() can start. In that case, it's just noise.</div><div class=""><br class=""></div><div class="">Félix</div><br class=""><div><blockquote type="cite" class=""><div class="">Le 28 août 2017 à 13:37, Adam Kemp via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> a écrit :</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I explained what the value is already. It identifies clearly in your code where the suspension points are. Each place you see “await” would mark a location where your code may yield and allow other things to happen. Those are points where state could change unexpectedly. It’s important for someone writing asynchronous code to understand where those locations are. It’s difficult to reason about your code without that knowledge.<div class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Aug 28, 2017, at 1:16 PM, Wallacy <<a href="mailto:wallacyf@gmail.com" class="">wallacyf@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">"Try" does the same, but I do not know anyone who prefers to repeat the same keyword several times.</div><div class=""><br class=""></div><div class="">return try func0(try func1(), try func2())<br class=""></div><div class=""><br class=""></div><div class="">I do not think there's any value in knowing how many interim steps also need "await" ... In practice, you have to wait for everyone anyway.<br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">Em seg, 28 de ago de 2017 às 17:09, Adam Kemp via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> escreveu:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">I decided to split this out to its own thread because it seems orthogonal to other issues being discussed.</div><div class=""><br class=""></div><div class="">When I read this line from the proposal:</div><div class=""><br class=""></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class="">await decodeImage(dataResource.get(), imageResource.get())</blockquote><div class=""><br class=""></div>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).<div class=""><br class=""></div><div class=""><div class="">I’m not a fan of the ambiguity of applying the await keyword to an entire statement. I know some people think this is a good thing, but to me it’s just obfuscating important information.</div><div class=""><br class=""></div><div class="">Further, if you’re going beyond a single expression then why you would stop at the statement level? Why not make it apply to the whole block or even a whole function? Why require the keyword at all? It doesn’t appear to be adding any value if it doesn’t specify exactly where the suspension point is. “Somewhere on this line” can get rather vague.</div><div class=""><br class=""></div><div class="">async/await can be a huge win for clarity, but it also comes with the downside of having to think a bit more about what can happen at these suspension points. I feel like it should be a goal to make it very clear where those suspension points are so that we can more easily reason about them. That’s why I prefer restricting it to apply to a single expression. It’s very clear where the function gets suspended, which means it’s clearer where you need to be concerned about things possibly happening in between your code. Consider this, for example:</div><div class=""><br class=""></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class="">await decodeImage(loadWebResource(self.webProfilePath), loadWebResource(self.imagePath))</blockquote><div class=""><br class=""></div>If webProfilePath and imagePath are vars then they could change in between those two calls. If you can’t see that these calls are suspending then you might not know to cache them up-front to ensure consistency:<div class=""><br class=""></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class=""><div class="">let webProfilePath = self.webProfilePath</div><div class="">let imagePath = self.imagePath</div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class="">await decodeImage(await loadWebResource(webProfilePath), await loadWebResource(imagePath))</blockquote><br class=""></div><div class="">I think a general guideline we should use when considering how this feature should work is to ask whether it makes bugs more likely or less likely. The goal should be to reduce bugs while simplifying code. If we simplify the code to the point where we’re making some bugs too subtle then we may be doing more harm than good.</div></div>_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></div></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>