<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On 13 Jul 2016, at 18:56, Pierre Habouzit &lt;<a href="mailto:phabouzit@apple.com" class="">phabouzit@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Jul 13, 2016, at 9:18 AM, Karl via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">#1 -<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">Currently, DispatchQueue.after() takes an absolute time as the “after” parameter. This makes it hard to understand how to use it; you need to go digging through generated interfaces to find out what a ‘DispatchTime’ is and how you construct it (by getting the .now() and adding a DispatchTimeInterval using one of the easily-missable operator overloads, if you were wondering).<br class=""><br class="">Here is what DispatchQueue.after looks like now:<br class=""><br class="">public func after(when: DispatchTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @convention(block) () -&gt; Void)<br class=""><br class="">So to use it, you have to type:<br class=""><br class="">DispatchQueue.main.after(when: DispatchTime.now() + .milliseconds(250)) &nbsp;&nbsp;{ /* do stuff */ }<br class=""><br class="">I don’t believe this is a great fit with the Swift API Guidelines. I believe the name “after” already implies that the time is relative, the argument label should be dropped, and that nuances about the clock (basically, whether or not it pauses during system sleep) are edge-cases which can be handled for the majority of users with a sensible default value (or better yet, modelling via an enum or boolean switch — see #2). Additionally, There are overloads with “wallTime” parameter labels which seem only to duplicate type information (the monotonic and walltime clocks are actually split at the type level) and could be more concise and readable. The principle is that, ultimately, you should just be able to write the above code like this:<br class=""><br class="">DispatchQueue.main.after(.milliseconds(250)) { /* do stuff */ }<br class=""><br class="">Or<br class=""><br class=""><a href="http://dispatchqueue.main.at/" class="">DispatchQueue.main.at</a>(DispatchTime.now() + .seconds(3)) { /* do stuff */ }<br class=""><br class="">It’s not something you use all the time (like .sync/.async), but I find that whenever I do need it I’m frustrated by how needlessly complex it is to decipher and use. I would find these methods much more obvious, I could figure out how to use them much more quickly, and I think I’d remember how to use them more quickly.<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">As mentioned by Matt in the pull request you created, we’re working on a proposal that would look like this:</div><div class=""><br class=""></div><div class=""><div class="timeline-comment-wrapper js-comment-container" style="box-sizing: border-box; position: relative; padding-left: 64px; margin-top: 15px; margin-bottom: 15px; border-top-width: 2px; border-top-style: solid; border-top-color: rgb(255, 255, 255); border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(255, 255, 255); color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px;"><div id="issuecomment-232280877" class=" timeline-comment js-reorderable-task-lists previewable-edit reorderable-task-lists js-comment 
 js-task-list-container
 comment" data-body-version="cbe98e79f13393e819787a8739ac23bd" style="box-sizing: border-box; position: relative; background-color: rgb(255, 255, 255); border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;"><div class="edit-comment-hide" style="box-sizing: border-box;"><div class="markdown-body comment-body markdown-format js-comment-body" style="box-sizing: border-box; line-height: 1.5; word-wrap: break-word; width: 694px; padding: 15px; overflow: visible;"><div class="highlight highlight-source-swift" style="box-sizing: border-box; background-color: transparent; margin-bottom: 0px !important; overflow: visible !important;"><pre class="" style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 11.899999618530273px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal;"><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">asyncAfter</span>(deadline:qos:flags:work:)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">asyncAfter</span>(wallDeadline:qos:flags:work:)</pre></div></div></div></div></div></div><div class="">As we discussed on the pull request,&nbsp;</div><div class=""><br class=""></div></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><div class="">DispatchQueue.main.after(.milliseconds(250)) { /* do stuff */ }</div></div></div></blockquote><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Is ambiguous as you don’t know which clock was meant, and despite your claim, there’s in general no good default for the clock. If you are writing a calendar app, you want wallClock, but if you’re doing anything network related, you will want the monotonic one. Depending on which software you’re writing, you will have a bias for one or the other.</span></div></blockquote><div><br class=""></div><div>Yeah I think we should split after(DispatchTime) and after(DispatchWallTime) to reflect their different ways of working.</div><div><br class=""></div><div>after(DispatchTime) stays as it is, because it reflects an elapsed number of ticks</div><div>after(DispatchWallTime) should be renamed. I suggested it should be at(DispatchWallTime), and should only take an absolute value.</div><div><br class=""></div><div>“after(deadline:)” isn’t better, I’m afraid. The definition is: "the latest time or date by which something should be completed.” We don’t really talk about “after” deadlines - deadlines are points in time you need to do something *before*. If something happens after a deadline, we say it “missed” the deadline. Like I said in the PR, that kind of timing guarantee is most clearly expressed by saying “by(deadline:)”.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Also it may be a native speaker thing (which I’m not) but this reads “please async this closure on `q` after this deadline has expired” to me, which sounds like proper english:</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class="">q.asyncAfter(deadline: .now() + 1.0) { /* do stuff */ }</div></blockquote><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">I thought that you would say “please meet me in 10 minutes” or “please meet me after 2PM”. The `asyncBy` that you suggested to the pull request reads *before* that deadline to me which is not good either.</div><div class="">`asyncAt` would probably work too however, but asyncAfter is easier for people coming from C who are used to dispatch_after().</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div class="">#2 -<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">Actually, while writing this down it’s becoming clearer and clearer that the idea to split DispatchTime (the monotonic clock) and DispatchWallTime (the wall clock) at the type level is probably a bad idea.<br class=""><br class="">Novice users are not going to understand what’s going on here - I expect most of them to default to the more generic-sounding “DispatchTime” without any idea of the implications of this. Perhaps we should look at replacing these clock variations with a more descriptive enum or boolean, rather than a separate type. For example:<br class=""><br class="">struct DispatchTime { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// replaces DispatchTime and DispatchWallTime<br class="">&nbsp;&nbsp;&nbsp;let rawValue : dispatch_time_t<br class="">&nbsp;&nbsp;&nbsp;let clock : Clock<br class=""><br class="">&nbsp;&nbsp;&nbsp;enum Clock { case monotonicClock; case wallClock }<br class="">}<br class=""><br class="">This would not obsolete the discussion at the start about “after”. The name “after” still implies that I want something done at some duration relative to an absolute point in time (usually now).<br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">This is what dispatch_time_t does in C and my team at Apple widely considers this having been a design mistake: it means that the time is not generally Comparable, that you can’t perform any kind of arithmetic with it, etc.</div><div class=""><br class=""></div><div class="">In C it’s more convenient to have a single type, but in Swift where type is inferred, given that most of the uses will construct the time as the argument to the function itself, we feel that the current proposal allows for the most concise use.</div><div class=""><br class=""></div></div></div></div></blockquote><br class=""></div><div>OK, the motivation to unify them was because it’s quite easy to get them confused when one is named “after(when: DispatchTime, …” and the other is named “after(walltime when: DispatchWallTime, …”</div><div><br class=""></div><div>Giving them more distinct function names would also work.</div><div><br class=""></div><div>Karl</div><br class=""></body></html>