<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="">Here's my review of "<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md" class="">SE-0073</a>: Marking closures as executing exactly once".</div><div><br class=""><blockquote type="cite" class=""><div class=""><span class="" style="font-family: Menlo-Regular; font-size: 11px; float: none; display: inline !important;">What is your evaluation of the proposal?</span><br class=""></div></blockquote><div><br class=""></div><div>+1. I think this is a good idea and should be <b class="">accepted</b> (without extending the proposed scope).</div><div><br class=""></div><div>However, I think the proposal should be more explicit about the case when (and whether) the block itself throws. Specifically, I think we should highlight that the criterion that</div><div><i class=""><br class=""></i></div><div><blockquote type="cite" class=""><i class="">it must not be executed on any path that throws</i></blockquote></div><div><br class=""></div><div>implies that <b class="">a <font face="Menlo" class=""><span style="font-size: 11px;" class="">@noescape(once)</span></font> parameter <i class="">itself</i> cannot throw</b> (until another language change allows otherwise). Consider this use case:</div><div><div class=""><br class=""></div><b style="font-family: Menlo; font-size: 11px;" class=""> final</b><span style="font-family: Menlo; font-size: 11px;" class=""> </span><b style="font-family: Menlo; font-size: 11px;" class="">class</b><span style="font-family: Menlo; font-size: 11px;" class=""> </span><span style="font-family: Menlo; font-size: 11px;" class="">Database {</span></div><div><span style="font-family: Menlo; font-size: 11px;" class=""> <b class="">final</b> <b class="">class</b> Transaction { ... }</span></div><div><font color="#919191" class=""><span style="font-family: Menlo; font-size: 11px;" class=""> </span><span style="font-family: Menlo; font-size: 11px;" class="">// Not allowed by SE-0073:</span></font></div><div><span style="font-family: Menlo; font-size: 11px;" class=""> </span><span style="font-family: Menlo; font-size: 11px;" class=""> </span><b style="font-family: Menlo; font-size: 11px;" class="">func</b><span style="font-family: Menlo; font-size: 11px;" class=""> </span><span style="font-family: Menlo; font-size: 11px;" class="">transact(_ </span><span style="font-family: Menlo; font-size: 11px;" class="">apply</span><span style="font-family: Menlo; font-size: 11px;" class="">: <font color="#ff2600" class="">@</font></span><font color="#ff2600" class=""><b style="font-family: Menlo; font-size: 11px;" class="">noescape</b><span style="font-family: Menlo; font-size: 11px;" class="">(</span><b style="font-family: Menlo; font-size: 11px;" class="">once</b><span style="font-family: Menlo; font-size: 11px;" class="">) (Transaction)</span><span style="font-family: Menlo; font-size: 11px;" class=""> </span><b style="font-family: Menlo; font-size: 11px;" class="">throws</b><span style="font-family: Menlo; font-size: 11px;" class=""> </span></font><span style="font-family: Menlo; font-size: 11px;" class=""><font color="#ff2600" class="">-> ()</font>)</span><span style="font-family: Menlo; font-size: 11px;" class=""> </span><span style="font-family: Menlo; font-size: 11px;" class=""><b class="">rethrows</b></span></div><div><span style="font-family: Menlo; font-size: 11px;" class=""> }</span></div><div><b style="font-size: 11px; font-family: Menlo;" class=""><br class=""></b></div><div><b style="font-size: 11px; font-family: Menlo;" class=""> func</b><span style="font-size: 11px; font-family: Menlo;" class=""> incrementScore(db: Database, game: String) </span><b style="font-size: 11px; font-family: Menlo;" class="">throws</b><span style="font-size: 11px; font-family: Menlo;" class=""> -> Int </span><span style="font-size: 11px; font-family: Menlo;" class="">{</span></div><div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> <b class="">let</b> oldScore: Int</span></font></div><div class=""><font face="Menlo" color="#919191" class=""><span style="font-size: 11px;" class=""> // This use of "@noescape(once) ... throws" *could* be ok if the error was</span></font></div><div class=""><font face="Menlo" color="#919191" class=""><span style="font-size: 11px;" class=""> // unconditionally propagated out of the scope of uninitialised variables:</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> <b class=""><font color="#ff2600" class="">try</font></b> db.transact { tx <b class="">in</b></span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> oldScore = <b class="">try</b> tx.read(key: "\(game).score")</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> <b class="">try</b> tx.update(key: "</span></font><span style="font-family: Menlo; font-size: 11px;" class="">\(game)</span><font face="Menlo" class=""><span style="font-size: 11px;" class="">.score", value: oldScore + 1)</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> <b class="">try</b> tx.update(key: "</span></font><span style="font-family: Menlo; font-size: 11px;" class="">\(game)</span><font face="Menlo" class=""><span style="font-size: 11px;" class="">.updatedAt", value: NSDate())<br class=""> }</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> <b class="">return</b> oldScore<br class=""> }<br class=""></span></font></div><div class=""><br class=""></div><div class="">Being able to throw out of a <font face="Menlo" class=""><span style="font-size: 11px;" class="">@noescape(once)</span></font> block would be useful in cases like this, as it would naturally allow rolling back a transaction. But it would complicate the language by requiring that no one catches the error in the scope where uninitialised variables are defined. I suggest adding this remark to the Future directions.</div></div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Menlo-Regular; font-size: 11px; 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 the problem being addressed significant enough to warrant a change to Swift?</span><br style="font-family: Menlo-Regular; font-size: 11px; 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=""></div></blockquote><div><br class=""></div><div>Yes. I'm looking forward to being able to initialise immutable variables in <font face="Menlo" class=""><span style="font-size: 11px;" class="">dispatch_sync</span></font> blocks and such without needing to resort to defining them as `<font face="Menlo" class=""><span style="font-size: 11px;" class=""><b class="">var</b></span></font>`.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Menlo-Regular; font-size: 11px; 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="">Does this proposal fit well with the feel and direction of Swift?</span><br style="font-family: Menlo-Regular; font-size: 11px; 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=""></div></blockquote><div><br class=""></div><div>Yes it does, it aligns nicely with the trailing closure syntax that allows for the emulation of control flow constructs with library code. And as we know, the control flow constructs already allow the delayed initialisation of local variables.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Menlo-Regular; font-size: 11px; 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="">If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?</span><br style="font-family: Menlo-Regular; font-size: 11px; 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=""></div></blockquote><div><br class=""></div><div>With a similar feature, I have only used languages (in the sense of "used in anger") where the delayed initialisation is allowed by allowing an undefined state (e.g. C++). For a not-really-applicable-to-Swift alternative approach, Haskell's laziness allows the recursive definition of variables for a similar effect.</div><div><br class=""></div><div>Finally, I think it's interesting that the requirement for <font face="Menlo" class=""><span style="font-size: 11px;" class="">@noescape(once)</span></font> arguments to be unconditionally executed has a similarity to linear type systems (<a href="https://en.wikipedia.org/wiki/Substructural_type_system" class="">Wikipedia</a>) and uniqueness or references. Except in this case, the reference is not to an object but a function. Such a function reference bears a certain similarity to the <font face="Menlo" class=""><span style="font-size: 11px;" class="">deinit</span></font> of a uniquely held object. I think the proposed feature may later merge with a bigger language update that brings reference uniqueness to the type system.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Menlo-Regular; font-size: 11px; 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="">How much effort did you put into your review? A glance, a quick reading, or an in-depth study?</span><br style="font-family: Menlo-Regular; font-size: 11px; 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=""></div></blockquote></div><div class=""><br class=""></div>Between quick reading and in-depth study.<div class=""><br class=""></div><div class="">— Pyry<br class="">
<br class=""></div></body></html>