<div dir="ltr"><div style="font-size:12.8px">I guess the core of the question for me is why have the concept of a closure at all when they're harder to read while acting the same way that functions do? I'm not a huge fan of Javascript, but the consistancy between function declarations and anonymous functions is something I feel they got right. JS syntax for everything that receives parameters and possibly returns a value is entirely consistent. </div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Let's take the anonymous function style:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"><font face="monospace, monospace">func asyncWithCallback(_ : func (String) -> Bool)</font></div><div style="font-size:12.8px"><font face="monospace, monospace"><br></font></div><div style="font-size:12.8px"><font face="monospace, monospace">asyncWithCallback(func (param) {</font></div><div style="font-size:12.8px"><font face="monospace, monospace"> return param == "string"</font></div><div style="font-size:12.8px"><font face="monospace, monospace">})</font></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Particularly for someone new to the language is both clearer and shorter than this, which makes the caller rewrite the return type in the closure:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"><font face="monospace, monospace">func asyncWithCallback(_ : String -> Bool)</font></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px"><font face="monospace, monospace">asyncWithCallback {</font></div><div style="font-size:12.8px"><font face="monospace, monospace"> (param: String) -> Bool in</font></div><div style="font-size:12.8px"><font face="monospace, monospace"> return param == "string"</font></div><div style="font-size:12.8px"><font face="monospace, monospace">}</font></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">It still fits your unwritten rule to be able to compose language features in Swift, assuming you leave the same syntactic sugar: <br></div><div style="font-size:12.8px"><pre style="white-space:pre-wrap;color:rgb(0,0,0)">func if (_ control: Bool, _ path: func ()) {</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)"> if (control) {</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)"> path()</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)"> }</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)">}</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)">if (a == b) {</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)"> //LETS DO SOME STUFF</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)">}</pre></div><div style="font-size:12.8px"><pre style="white-space:pre-wrap"><pre style="white-space:pre-wrap"><font face="arial, sans-serif"><span style="white-space:normal">I know it's a big change to the language, but I feel like it's better in just about every case I can think of without losing the Swiftiness we all enjoy. It certainly makes this easier to read. Even in one of the examples in the Swift guide (</span></font><font face="arial, sans-serif"><span style="white-space:normal"><a href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html" target="_blank">https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html</a>)</span></font><span style="white-space:normal;font-family:arial,sans-serif"> you're essentially using the syntax i'm proposing on the incrementer:</span></pre><pre style="white-space:pre-wrap"><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal">func makeIncrementer(forIncrement amount: Int) -> () -> Int {</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> var runningTotal = 0</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> func incrementer() -> Int {</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> runningTotal += amount</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> return runningTotal</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> }</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> return incrementer</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal">}</span></font></pre></pre><pre style="white-space:pre-wrap"><pre style="white-space:pre-wrap"><span style="white-space:normal;font-family:arial,sans-serif">I can't really fix the unclear chained return in the declaration, but doesn't the return of the anonymous function look similar to the above, just as you would expect?</span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace">func makeIncrementer(forIncrement amount: Int) -> func() -> Int {</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace"> var runningTotal = 0</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace"> return func () -> Int {</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace"> runningTotal += amount</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace"> return runningTotal</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace"> }</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="monospace, monospace">}</font></span></pre><pre style="white-space:pre-wrap"><span style="white-space:normal"><font face="arial, helvetica, sans-serif">But if I wanted to use closure syntax, It'd be different from the example above in the Swift handbook for no real good reason:</font></span></pre><pre style="white-space:pre-wrap"><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal">func makeIncrementer(forIncrement amount: Int) -> () -> Int {</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> var runningTotal = 0</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> return {</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> () -> Int in </span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> </span></font><span style="white-space:normal;font-family:monospace,monospace">runningTotal += amount</span></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> return runningTotal</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal"> }</span></font></pre><pre style="white-space:pre-wrap"><font face="monospace, monospace"><span style="white-space:normal">}</span></font></pre></pre></pre></pre></div><div style="font-size:12.8px">In the commonly rejected list, Jordan wrote:</div><div style="font-size:12.8px"><pre style="white-space:pre-wrap;color:rgb(0,0,0)">"We thought a lot about this, and settled on the current syntax (inside the braces) for several reasons, the main one being that it's much easier to parse. Without this, the compiler would have to stop whatever it's currently doing when it sees '->'."</pre><pre style="white-space:pre-wrap;color:rgb(0,0,0)"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;white-space:normal">I don't believe that's a problem when using the proposed func syntax, since by definition "->" will only follow a func (param) statement in all cases. The compiler can make more assumptions about what it's parsing. I think it might limit what you have to work with to the compilers benefit.</span></pre><pre style="white-space:pre-wrap"><font face="arial, sans-serif"><span style="white-space:normal">Thanks,</span></font></pre><pre style="white-space:pre-wrap"><font face="arial, sans-serif"><span style="white-space:normal">- Ethan</span></font></pre></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 28, 2015 at 5:44 PM, Chris Lattner <span dir="ltr"><<a href="mailto:clattner@apple.com" target="_blank">clattner@apple.com</a>></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"><br><div><span class=""><blockquote type="cite"><div>On Dec 27, 2015, at 2:30 PM, Ethan Diamond via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br><div><div dir="ltr">I realize this is on the commonly rejected list, but I really find closure syntax to be one of the more unintuitive and unreadable parts of Swift so I'd like to try to influence it. "Clarity at the point of use" is one of the main stated goals of Swift, and the fact that <a href="http://goshdarnclosuresyntax.com/" target="_blank">http://goshdarnclosuresyntax.com/</a> exists shows me that it's not just me that thinks the syntax could be improved. I believe that we can get very close to the same results in line length and expressiveness while making the language much more readable and clear.</div></div></blockquote><div><br></div></span><div>FWIW, I think that web site exists as a continuation of the “blocks” web site.</div><div><br></div><div>From your description, it sounds like you might want to try out nested functions. They have a more explicit syntax, and still provide the same “closure” power as closure expressions.</div><div><br></div><div>-Chris</div><br><blockquote type="cite"><div><div><div class="h5"><div dir="ltr"><div><br></div><div>Let's start with a few use cases to illustrate what I mean when I say that reading closure syntax is difficult. Most programmers scan left to right, so when I see this property declaration:</div><div><br></div><div>var thing: Int</div><div><br></div><div>My brain reads that as a property of a class that's an integer. Unless of course there's this:</div><div><br></div><div>var thing: Int -> Int</div><div><br></div><div>Boom, context switch. If you've read "Int" than any following syntax should be a modifier on Int. For example, Int? works great, because in my head it's still an Integer, just an optional form of that Integer. While it's not a huge change in that example, lets take a more complicated one:</div><div><br></div><div>var thing: (String -> (), Int, (Int, Int) -> Bool)) -> Bool</div><div><br></div><div>Reading that left to right requires all sorts of context switching in my brain. I can't even tell at first glance how many params are in that closure. Reading left to right, you read "First parameter, string, no wait, closure that takes string, and returns void. Second param, Int. Third param, tuple with two ints, no wait, closure that takes two ints and returns bool." I just doesn't have much clarity.</div><div><br></div><div>I believe it's already been proposed, but I don't feel there's a strong enough difference between a closure and a function to justify a different syntax. Let's replace my examples above with anonymous function syntax.</div><div><br></div><div>var thing: func (Int) -> Int</div><div><br></div><div>Reading left to right, it reads the way that I think about it "A function that takes an integer and returns an integer."</div><div><br></div><div>var thing: func(func (String), Int, func (Int, Int) -> Bool) -> Bool</div><div><br></div><div>Again, reading left to right this is a win. "Thing is an anonymous function. First param, a function that takes a string. Second param, Int. Third param, a function that takes two ints and returns bool." It reads like people think.</div><div><br></div><div>Another strength is it lets us both use the same syntax for closures as we would expect, while letting us use just about all of the same shorthands we gain with closures. We could call normally like this, with the return type implied when async is called:</div><div><br></div><div>func async(callback: func (Bool) -> Bool))</div><div><br></div><div>async(func (successful: Bool) {</div><div> return !successful<br></div><div>});</div><div><br></div><div>We could still permit this:</div><div><br></div><div>func async(callback: func ())</div><div><br></div><div>async {</div><div> //Do callback stuff here</div><div>}</div><div><br><div>We could still permit this:</div><div><br></div><div>func sort(sortfunc: func(Int, Int) -> Bool)</div><div><br></div><div>sort {</div><div> $0 > $1</div><div>}</div><div><br></div></div><div>We could add this:</div><div><br></div><div>let greaterThan: func (number: Int) -> Bool = {</div><div> number > 5</div><div>}</div><div><br></div><div>There would also be a few small wins, such as no longer needing "()" to represent a void return, since any function without a return type would imply a void return.</div><div><br></div><div>I understand that a big part of the decision for current closure syntax is to help the compiler, but I believe by doing so you're going against the main principles you laid out in your api design guidelines (<a href="https://swift.org/documentation/api-design-guidelines.html" target="_blank">https://swift.org/documentation/api-design-guidelines.html</a>). Current closure syntax is not clear and breaks precedent of all other function like declarations having the parameters listed outside of the curly braces.</div><div><br></div><div>Thanks for listening, and great job on Swift so far.</div></div>
</div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=RC5Cq0zAxCHc1sM9Uy3-2BojrrUAw-2F96zH69NULNHPvCv3bvM5ehXrBN82Adgocc41YRvZisAPOwLlcicwXU6S0alCbgnP6U-2F1RUKS36NTN1Lp5snXhGYpUrwjQKJtjm8wbU6mwxDMN6koR0CswpZc4LcGRd29wKS0kIPeyK1jeDWhIj-2BAip92PG0q1UJEbwVOROswmShbN9oCsYiOh2sbH20kJNga2qRhhyvfyfvAuN4-3D" alt="" width="1" height="1" border="0" style="min-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">
_______________________________________________<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></div></blockquote></div><br></div>