<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 5 Jan 2017, at 02:25, Jay Abbott 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=""><div dir="ltr" class=""><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important" class="">When you have a function with a closure and then another optional default <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline" class="">= nil</code> closure at the end, like this:</p>
<pre style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px" class=""><code class="language-swift hljs" style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248) none repeat scroll 0% 0%">open <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">static</span> <span class="hljs-func"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">func</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">animate</span><span class="hljs-params">(identifier: String,
duration: Double,
update: @escaping AnimationUpdate,
completion: AnimationCompletion? = <span class="hljs-built_in" style="color:rgb(0,134,179)">nil</span>)</span> </span>{
</code></pre><p style="margin:0px 0px 1.2em!important" class="">You can’t use trailing closure syntax for the <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline" class="">update</code> argument when leaving the <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline" class="">completion</code> argument out/default.</p><p style="margin:0px 0px 1.2em!important" class="">This kind of breaks one of the benefits of default arguments, which is that you can add them to existing released functions without breaking the calling code. This means you have to add a separate convenience function without the extra argument, which is annoying and inelegant. Another annoying thing is that you can easily miss this error if you happen to not use trailing closure syntax in your tests or other usage, because adding the extra default argument compiles fine for code that uses normal syntax.</p><p style="margin:0px 0px 1.2em!important" class="">Are there any issues/gotchas if the trailing closure syntax were to work for the last <em class="">specified</em> argument rather than the last <em class="">defined</em> argument?</p></div></div></div></blockquote></div><div>I'm not sure I'd call having another convenience function "annoying and inelegant" personally, as that's kind of the whole point of them, but yes I do agree in this case it could be handled more easily.</div><div><br class=""></div><div>Personally I like the idea of having a new @trailing attribute to allow any closure to be specified as the trailing closure, regardless of placement, as this would also be useful for methods where you may accept multiple closures, but where it may make the most logical sense to have say a main body closure as the first parameter, yet it also makes most sense to be the trailing closure, which becomes awkward.</div><div><br class=""></div><div>I'm not in favour at all of allowing multiple trailing closures as someone mentioned, I think one is enough (and even then, I only really like them personally for language-construct like methods such as .forEach and similar).</div><div><br class=""></div><div><br class=""></div><div>However, I think the real issue in this specific example is that the function/method is being modified after its initial definition, and I wonder if this falls into the ability to reorder arguments? Since most Swift methods and functions have argument labels it doesn't necessarily matter if they are given in a different order as they are still well-defined; thing is, I think Swift actually had this ability and no-one was using it so I don't know if reintroducing it would be the right fix, unless perhaps it is done as an attribute of the function/method?</div><div><br class=""></div><div>For example:</div><div><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><font face="Monaco" class="">@reorderable</font></div><div><font face="Monaco" class="">static func animate(identifier: String, duration: String, update: @escaping AnimationUpdate, completion: AnimationCompletion? = nil) { … }</font></div></blockquote><div><br class=""></div><div>With this attribute the order of the parameters is no-longer fixed, but as update is still the last closure it is considered to be the trailing closure? A @trailing attribute would still be useful in this case though as it's possible the new parameter(s) might include a new closure, and you wouldn't want it to suddenly become the new trailing closure.</div><div><br class=""></div><div>Also, can't test right now, but can you not add your new completion parameter before the update closure? This should still satisfy existing calls to the method while allowing others to optionally set the completion parameter?</div><div><br class=""></div><div><br class=""></div><div>Finally, one other interesting thought, but could we simply allow trailing closures to be any closure the developer hasn't defined? For example:</div><div><br class=""></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>function myFunc(body:() -> Void, loop: () -> Bool) { … }</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>myFunc(loop: myLoopClosure) { /* this is the body */ }</font></div><div><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>myFunc(body: myBodyClosure) { /* this is the loop closure */ }</font></div><div><br class=""></div><div>Perhaps that's a bit too confusing and should be activated with an attribute, but it should be possible to allow this as in both calls above the closure that is trailing is unambiguous.</div><div><br class=""></div><div><br class=""></div><div>Just my thoughts on all possible solutions I can think of ;)</div></body></html>