<div dir="ltr">+1<div><br></div><div>I&#39;ve wanted the ability require that a closure be called for a little while now. Clean up code is an example of when this can be useful.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jan 30, 2016 at 9:54 PM, Félix Cloutier <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Can the compiler even enforce it? If the closure escapes, it necessarily means that you assigned it elsewhere. How do you enforce that you never call this reference more than once?<div><br></div><div>If the compiler can&#39;t take advantage of it and can&#39;t enforce it either, I would rather not have it at all.<br><div><br></div><div>I would also think that for a lot of APIs with an escaping closure, it could be more useful to say that it will be called &quot;at most once&quot; than &quot;exactly once&quot;. Additionally, if completion blocks are the main client of the feature, I would avoid giving it too much effort before we figure out the favored concurrency model.</div><div><br></div><div>@noescape(once) really looks like a special case to me, because it&#39;s enforceable, useful to the compiler and useful to the user.<br><div><div><div>
<br><span style="color:rgb(0,0,0);font-family:&#39;Lucida Grande&#39;;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;display:inline!important;float:none">Félix</span>
</div><div><div class="h5">
<br><div><blockquote type="cite"><div>Le 30 janv. 2016 à 15:07:11, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" target="_blank">matthew@anandabits.com</a>&gt; a écrit :</div><br><div><blockquote type="cite" style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><br>On Jan 30, 2016, at 1:56 PM, Félix Cloutier via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word">I agree that many closures are expected to be executed only once, but it seems to me that it&#39;s only useful to the compiler if it&#39;s also marked @noescape. A completion handler marked &quot;once&quot; without &quot;noescape&quot; doesn&#39;t allow the compiler to determine that a variable will have been initialized after the call that takes the closure.<div><div><br></div><div>So in these other cases, it only serves as documentation. I&#39;m not very enthusiastic about attributes that only serve as documentation because there is an infinity of attributes that can be added to the language for documentation purposes.</div></div></div></div></blockquote><div style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">It also serves as a guarantee that the closure is executed exactly once.  Even if the compiler can’t use it for optimization the guarantee could be useful.</div><br style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite" style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><div style="word-wrap:break-word"><div><div><br></div><div>There are other places than `dispatch_sync` where you may want a `@noescape(once)` attribute. Any function that executes a closure while providing some sort of guarantee/RAII-like handle can benefit from it. Most of the functions starting with `with` in the standard library could benefit from it: withExtendedLifetime, withUnsafePointer and friends, withVaList. String&#39;s `withCString` and `withMutableCharacters` could benefit from it too. Someone who writes a `withLock(lock) { closure }` function would be happy to have it too.<br><div><div><br><span style="font-family:&#39;Lucida Grande&#39;;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">Félix</span></div><br><div><blockquote type="cite"><div>Le 30 janv. 2016 à 07:11:23, Rod Brown &lt;<a href="mailto:rodney.brown6@icloud.com" target="_blank">rodney.brown6@icloud.com</a>&gt; a écrit :</div><br><div><div dir="auto"><div>I&#39;m very supportive of this type of proposal.</div><div><br></div><div>I do agree with Brent though that @noescape and &#39;once&#39; is somewhat orthogonal.</div><div><br></div><div>There are a lot of places where you want to be clear that the block will be called but no more than once. For example, the NSURLSession callback blocks you would expect never to be called multiple times. Completion handlers are almost always used only once. I don&#39;t think this case, which is extremely common, can be overlooked.</div><div><br></div><div>On the other hand, I suspect the majority of places you use closures with @noescape, it seems more likely you&#39;d<span> </span><i>want<span> </span></i>it used multiple times, like a search, filter, find etc of multiple items in a collection or group, otherwise you&#39;d generally just put the closured activity before or after. The only areas where I would expect to see such closures of @noescape and &#39;once&#39; would be dispatch_sync, or somewhere where you want to invoke custom code in the middle of a complex operation of a method.</div><div><br></div><div>It seems to me that separating them, but allowing them to be used together, makes more sense.</div><div><br></div><div>Rod</div><div><br></div><div><br>On 30 Jan 2016, at 5:05 AM, Félix Cloutier via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div>I don&#39;t have much to add but I also think that it would be nice to have.<div><div><div><br><span style="font-family:&#39;Lucida Grande&#39;;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">Félix</span></div><br><div><blockquote type="cite"><div>Le 29 janv. 2016 à 12:38:01, Chris Lattner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; a écrit :</div><br><div><span style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">On Jan 29, 2016, at 12:23 AM, Jacob Bandes-Storch via swift-evolution &lt;</span><a href="mailto:swift-evolution@swift.org" style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">swift-evolution@swift.org</a><span style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">&gt; wrote:</span><div style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite"><div><div dir="ltr">I&#39;ve wanted something like this as well. I think it would be harder than it seems, because &quot;x = 1&quot; might need to perform initialization, or assignment, depending how it&#39;s used.<div><br></div><div>It could make sense to have something like &quot;@noescape(executed_exactly_once)&quot; but this might be so limited it&#39;s not worth it. And I&#39;m not sure how it should interact with throws.</div></div></div></blockquote><div><br></div><div>I think that something like this is implementable, and making it a modifier to @noescape is sensible.</div><div><br></div><div>The semantics we could support is that the function is guaranteed to call the closure exactly once on any path that could lead to a return or throw.</div><div><br></div><div>This approach allows you to pass the closure down the stack, and composes with error handling.  It is obviously limited what you can do with the closure, but that is necessary to validate correctness.</div><div><br></div><div>-Chris</div><div><br></div><div><br></div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><br clear="all"><div><div><div dir="ltr"><div>Jacob<br></div></div></div></div><br><div class="gmail_quote">On Thu, Jan 28, 2016 at 11:38 PM, Gwendal Roué<span> </span><span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">Hello,<div><br></div><div>I’d like to discuss the opportunity to let functions declare that a closure argument is guaranteed to have been executed when the function has returned.</div><div><br></div><div>For example:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)"><span style="white-space:pre-wrap">        </span>func</span><span> </span>f(<span style="color:rgb(187,44,162)">@noescape</span>(<span style="color:rgb(112,61,170)">executed</span>) closure: () -&gt; ()) {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="white-space:pre-wrap">        </span>    closure()</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="white-space:pre-wrap">        </span>}</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div></div><div>The expected advantage is that the compiler would know that a variable set inside the closure is guaranteed to be initialized, and that it can be used after the execution of the function, as below:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><div style="margin:0px;line-height:normal;color:rgb(0,132,0)"><span style="color:rgb(187,44,162)"><span style="white-space:pre-wrap">        </span>let</span><span><span> </span>x:<span> </span></span><span style="color:rgb(112,61,170)">Int</span><span> <span> </span></span>// Not initialized</div><div style="margin:0px;line-height:normal"><span style="color:rgb(49,89,93)"><span style="white-space:pre-wrap">        </span>f</span><span> </span>{<span> </span><span style="color:rgb(79,129,135)">x</span><span> </span>=<span> </span><span style="color:rgb(39,42,216)">1</span><span> </span>}</div><div style="margin:0px;line-height:normal;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)"><span style="white-space:pre-wrap">        </span>print</span><span>(</span><span style="color:rgb(79,129,135)">x</span><span>)   <span> </span></span>// Guaranteed to be initialized</div><div><br></div></div></div><div>Today developers have to write pessimistic code like below:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(187,44,162)"><span style="white-space:pre-wrap">        </span>var</span><span><span> </span>x:<span> </span></span><span style="color:rgb(112,61,170)">Int</span><span><span> </span>=<span> </span></span><span style="color:rgb(39,42,216)">0</span><span><span> </span></span>// `var` declaration, with some irrelevant value</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(49,89,93)"><span style="white-space:pre-wrap">        </span>f</span><span> </span>{<span> </span><span style="color:rgb(79,129,135)">x</span><span> </span>=<span> </span><span style="color:rgb(39,42,216)">1</span><span> </span>}</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(61,29,129)"><span style="white-space:pre-wrap">        </span>print<span>(</span><span style="color:rgb(79,129,135)">x</span><span>)</span></div></div><div><span><br></span></div><div>As for a real world usage, I’d like to access a database in a safe (queued) way, and fetch values out of it:</div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)"><span style="white-space:pre-wrap">        </span>let</span><span> </span>items: [<span style="color:rgb(79,129,135)">Item</span>]</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)"><span style="white-space:pre-wrap">        </span>let</span><span> </span>users: [<span style="color:rgb(79,129,135)">User</span>]</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(49,89,93)"><span style="color:rgb(79,129,135)"><span style="white-space:pre-wrap">        </span>dbQueue</span><span>.</span>inDatabase<span><span> </span>{ db<span> </span></span><span style="color:rgb(187,44,162)">in</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="white-space:pre-wrap">        </span>   <span> </span><span style="color:rgb(79,129,135)">items</span><span> </span>=<span> </span><span style="color:rgb(79,129,135)">Item</span>.all().fetchAll(db)</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="white-space:pre-wrap">        </span>   <span> </span><span style="color:rgb(79,129,135)">users</span><span> </span>=<span> </span><span style="color:rgb(79,129,135)">Item</span>.all().fetchAll(db)</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="white-space:pre-wrap">        </span>}</div></div><span><font color="#888888"><div><br></div><div>Gwendal Roué</div><div><br></div></font></span></div><br>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br><br></blockquote></div><br></div></div>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">_______________________________________________</span><br style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">swift-evolution mailing list</span><br style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><a href="mailto:swift-evolution@swift.org" style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">swift-evolution@swift.org</a><br style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family:LucidaGrande;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br></div></div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></div></blockquote></div><br></div></div></div></div>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div></blockquote></div><br></div></div></div></div></div></div></div><br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>