<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="">Hi, Tommy. Just to make things clear: it's fine for people to discuss this as brainstorming on the list, but addressing concurrency issues is an <a href="https://github.com/apple/swift-evolution#out-of-scope" class="">explicit non-goal for Swift 3</a>. We'll probably come back to it in the future, but that's still a ways off.</div><div class=""><br class=""></div><div class="">Best,</div><div class="">Jordan</div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 9, 2015, at 8:14, Tommy van der Vorst via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Dear all,<div class=""><br class=""></div><div class="">In the past few months I have been using Swift to write Warp (<a href="http://warp.one/" class="">http://warp.one</a>) a data analysis/ETL app for OS X (±80k LOC). In this app I make heavy use of GCD (dispatch queues) and asynchronous calls. Although Swift has greatly simplified working with asynchronous operations for me compared to Objective C, asynchronous operations are still not really first-class citizens;</div><div class=""><br class=""></div><div class=""><ol class="MailOutline"><li class="">The standard library does not really define how errors should be handled in asynchronous scenarios. The throw/catch mechanism obviously doesn't work for asynchronous operations. </li><li class="">While the compiler checks if a function that returns a value returns one in all possible code paths, the compiler currently doesn't check whether an asynchronous function always 'calls back'. Also, while the compiler prevents you from returning twice from a function, it currently does not prevent you from calling a callback more than once (some callbacks actually are intended to be called more than once of course, but in most cases, but many aren't).</li><li class="">Currently you cannot make any assumptions about the queue/thread on which a callback will be called. This is especially problematic when you want to make UI updates from a callback - all you can do is dispatch_async your updates to the main queue. </li></ol></div><div class=""><br class=""></div><div class="">Re 1, Error handling: in my own code I have defined a type that represents a 'failable' operation (more or less an Optional<T> with either a result object or an error message). I propose the standard library defines such a type before library authors all invent one themselves. My current version is listed below.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 143, 0);" class="">/** Fallible<T> represents the outcome of an operation that can either fail (with an error message) or succeed</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 143, 0);" class="">(returning an instance of T). */</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">public</span> <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">enum</span> Fallible<T> {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">case</span> Success(T)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">case</span> Failure(String)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">public</span> <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">init</span><P>(<span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">_</span> other: <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Fallible</span><<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">P</span>>) {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">switch</span> other {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">case</span> .Success(<span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">let</span> s):</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">self</span> = .<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Success</span>(s <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">as</span>! <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">T</span>)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">case</span> .Failure(<span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">let</span> e):</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">self</span> = .<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Failure</span>(e)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span>@warn_unused_result(message="Deal with potential failure returned by .use, .require to force success or .maybe to ignore failure.")</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">public</span> <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span> use<P>(<span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">@noescape</span> block: <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">T</span> -> <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Fallible</span><<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">P</span>>) -> <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Fallible</span><<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">P</span>> {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span></span>switch<span style="font-variant-ligatures: no-common-ligatures;" class=""> </span>self<span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">case</span> Success(<span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">let</span> box):</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span> block(box)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">case</span> Failure(<span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">let</span> errString):</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span> .<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">Failure</span>(errString)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="font-family: Helvetica; font-size: 12px;" class="">Re 2 (callbacks and returns): the way I currently 'solve' this is to wrap callbacks as follows, so that I get an assertion failure each time a callback is called more than once, so at least I find this out in testing. This doesn't solve the problem of functions not calling back at all:</div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">public</span> <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span> Once<P, R>(block: ((<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">P</span>) -> (<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">R</span>))) -> ((<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">P</span>) -> (<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">R</span>)) {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">var</span> run = <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">false</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span>#if<span style="font-variant-ligatures: no-common-ligatures;" class=""> </span>DEBUG</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span> {(p: <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">P</span>) -> (<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">R</span>) <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">in</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(180, 38, 26);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>assert(!run, </span>"callback called twice!"<span style="font-variant-ligatures: no-common-ligatures;" class="">)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>run = <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">true</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span> block(p)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span>#else</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">return</span> block</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span>#endif</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class="">it would be great if closures (or callback parameters) could be annotated with an attribute that indicates how many times the callback should be called under normal circumstances, e.g.:</div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="color: rgb(4, 51, 255);" class="">func</span> foo(callback: @once (<span style="color: rgb(52, 149, 175);" class="">Result</span>) -> ()) { ... }</div></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Helvetica; font-size: 12px;" class="">In this example, the callback </span><span style="font-family: Helvetica; font-size: 12px;" class="">must either be called exactly once in the body of the foo function, or passed exactly once to another function expecting an @once callback, or should be captured in one closure that always calls the callback once. The compiler should check whether all code paths lead to a single callback, and that no code paths lead to multiple callback invocations. The dispatch_sync and dispatch_async functions are examples of asynchronous functions with @once semantics.</span></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-family: Helvetica; font-size: 12px;" class="">Re 3 (the thread on which a callback is invoked): I currently 'solve' this by adding an assert to functions that can only be called on the main thread to ensure they are not called on another thread. </span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">public</span> <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">func</span> AssertMainThread(file: <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">StaticString</span> = <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">__FILE__</span>, line: <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">UInt</span> = <span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">__LINE__</span>) {</div><div style="margin: 0px; line-height: normal; color: rgb(180, 38, 26);" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">assert</span><span style="font-variant-ligatures: no-common-ligatures;" class="">(</span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">NSThread</span><span style="font-variant-ligatures: no-common-ligatures;" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">isMainThread</span><span style="font-variant-ligatures: no-common-ligatures;" class="">(), </span>"Code at <span style="font-variant-ligatures: no-common-ligatures;" class="">\</span>(<span style="font-variant-ligatures: no-common-ligatures;" class="">file</span>):<span style="font-variant-ligatures: no-common-ligatures;" class="">\</span>(<span style="font-variant-ligatures: no-common-ligatures;" class="">line</span>) must run on main thread!"<span style="font-variant-ligatures: no-common-ligatures;" class="">)</span></div><div style="margin: 0px; line-height: normal;" class="">}</div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-family: Helvetica; font-size: 12px;" class="">It might be worthwhile to add an attribute to mark functions as 'must always execute on main thread' (or 'must never execute on main thread' for blocking operations). 'Proving' that such a call actually never happens is more difficult however (but at least the attribute provides proper documentation and we can add assertions that check it automatically in debug mode).</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class="">Curious to see what you think. I would be willing to write a more formal/complete proposal for these suggestions, if you think they might be valuable additions to the Swift language and standard library.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">Best regards,</div><div style="margin: 0px; line-height: normal;" class="">Tommy.</div><div class=""><br class=""></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=ZEz4qHYnXhPr3bBPu-2FxP4tN3HfWKL-2FtJpqkQ0gkOVSDhIm5B2djK8OkTgWYk7D1jnS4qjlPlrf2tFl2epMMOfgauyPRfGvGz3l97t-2F2jhZirRHhvP61772cGMNi516TsfhoWmVq8g6T7UmEiyeuKgf9DAyanroslNjfNrA823BKHNWPoWbjG5-2BlJQR4pls71I-2FGlFUUFcPnCGgPUI14FZElgyKzjlDzbDHw5AUWWnfs-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</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>