<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 style="font-size: 16px;" class="">Last week, I made the following proposal for Swift:</div><div style="font-size: 16px;" class=""><br class=""></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><p style="box-sizing: border-box; font-size: 19px; margin: 0px 0px 15px; line-height: inherit; color: rgb(61, 48, 47); font-family: Georgia, serif;" class="">The C-style <code style="box-sizing: border-box; font-family: 'andale mono', 'lucida console', monospace; font-size: 15px; white-space: pre-wrap; width: auto;" class="">for-loop</code> appears to be a mechanical carry-over from C rather than a genuinely Swift-specific construct. It is rarely used and not very Swift-like.</p><p style="box-sizing: border-box; font-size: 19px; margin: 15px 0px; line-height: inherit; color: rgb(61, 48, 47); font-family: Georgia, serif;" class="">More Swift-typical construction is already available with <code style="box-sizing: border-box; font-family: 'andale mono', 'lucida console', monospace; font-size: 15px; white-space: pre-wrap; width: auto;" class="">for-in</code> statements and <code style="box-sizing: border-box; font-family: 'andale mono', 'lucida console', monospace; font-size: 15px; white-space: pre-wrap; width: auto;" class="">stride</code>. Removing for loops would simplify the language and starve the most common use-points for <code style="box-sizing: border-box; font-family: 'andale mono', 'lucida console', monospace; font-size: 15px; white-space: pre-wrap; width: auto;" class="">--</code> and <code style="box-sizing: border-box; font-family: 'andale mono', 'lucida console', monospace; font-size: 15px; white-space: pre-wrap; width: auto;" class="">++</code>, which are already due to be eliminated from the language.</p><p style="box-sizing: border-box; font-size: 19px; margin: 15px 0px 0px; line-height: inherit; color: rgb(61, 48, 47); font-family: Georgia, serif;" class="">The value of this construct is limited and I believe its removal should be seriously considered.</p></div></blockquote><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">Yesterday, I was on family time. Today, I am grabbing a little Swift-break to respond to the discussion I otherwise missed on-list. Please forgive the lateness of this response.</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><b class="">Lack of Language Necessity</b></div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">Clemens writes:</div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><blockquote type="cite" style="font-family: Palatino-Roman;" class="">We’ve developed a number of Swift apps for various clients over the past year and have not needed C style for loops either.</blockquote></div><div class=""><br style="font-family: Palatino-Roman;" class=""></div><div class=""><span style="font-family: Palatino-Roman;" class="">But I think this is a very weak reason for *removing* any portion like C-loops and increment or decrement operators of a programming language. How about the developers and the productive code which used C-style loops already?</span></div><div class=""><br style="font-family: Palatino-Roman;" class=""></div><div class=""><span style="font-family: Palatino-Roman;" class="">I understand the reasons why you, Erica and the others don’t like C-style loops. But changing the philosophy of a productive programming language is a very bad idea.</span></div></blockquote><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">I don't think the C-style loop was ever really part of the language philosophy. It feels like a vestigial feature that no one ever got around to cleaning up. Its entire functionality is easily replaced by other, existing Swift constructs. While Swift design deliberately held onto C-like features for familiarity, I see no special benefit to retaining the for-loop.</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">In contrast, consider <font face="Courier" class="">fallthrough</font>. There was a discussion on Friday about <font face="Courier" class="">fallthrough</font>, and it quickly became apparent that losing this language feature would have a significant impact on a few key algorithms. Several list participant were able to pop forward and say "without this feature, I would not be able to do X, Y or Z". I see no parallel case to be made for for-loops.</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><b class="">Lowered Readability and Maintainability</b></div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">I have aesthetic reasons for disliking the for-loop. The C-style loop is harder to read especially for those not coming from C-style languages, easier to mess up at edge conditions, and is commonly used for side-effects which, in a language focused on safety, is not a feature to be encouraged. </div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">For example, one side effect that was mentioned on-list yesterday was the incrementor, which is guaranteed in C-style to execute late:</div><div class=""><div style="font-size: 16px;" class="">Roland King writes:</div><blockquote style="font-size: 14px; margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><div class="" style="font-family: Palatino-Roman;">for var floatingThing = start ; floatingThing <= end ; floatingThing += delta</div><div class="" style="font-family: Palatino-Roman;">{</div><div class="" style="font-family: Palatino-Roman;"><span class="Apple-tab-span" style="white-space: pre;">        </span>// more than a few lines of code with early escape continues</div><div class="" style="font-family: Palatino-Roman;">}</div><div class="" style="font-family: Palatino-Roman;"><br class=""></div><div class="" style="font-family: Palatino-Roman;">shows intent of the loop very clearly, start, condition and increment all together at the top, and however you loop you always execute the increment part of the statement. Convert that to a while(), if you have a continue in the body, you have a good chance of not incrementing at all, or duplicating the increment code before every continue. So you can’t always nicely turn for into while. I second the point below about the loop variable being local to the for as well, I also like that. </div><div class="" style="font-family: Palatino-Roman;"><br class=""></div></div></blockquote><span style="font-size: 16px;" class="">Late incrementor management is a feature that can be mimicked with defer, as pointed out by several other list members.</span><font face="Palatino-Roman" size="3" class=""><br class=""></font><blockquote style="font-size: 14px; margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div style="font-size: 16px;" class=""><div class=""><br class=""></div></div></blockquote></div><div style="font-size: 16px;" class="">Another complaint regarded a loss of succinctness. Per Melin wrote: </div><div style="font-size: 16px;" class=""><br class=""></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><div style="font-family: Palatino-Roman;" class="">Another example from the same LinkedList class. It finds the right place to insert a new node:</div></div><div class=""><div style="font-family: Palatino-Roman;" class=""><br class=""></div></div><div class=""><div style="font-family: Palatino-Roman;" class=""><div style="margin: 0px; font-size: 18px; font-family: Inconsolata;" class=""><span style="color: rgb(187, 44, 162);" class=""> for</span> next = <span style="color: rgb(79, 129, 135);" class="">head</span>; next != <span style="color: rgb(187, 44, 162);" class="">nil</span> && index > <span style="color: rgb(39, 42, 216);" class="">0</span>; prev = next, next = next!.<span style="color: rgb(79, 129, 135);" class="">next</span>, --index { }</div></div></div><div class=""><div style="font-family: Palatino-Roman;" class=""><br class=""></div></div><div class=""><div style="font-family: Palatino-Roman;" class="">Extreme? Probably, but I like it better than the same thing done in five lines of while loop.</div></div></blockquote><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">I'd argue that readability and maintainability are core API goals. Clarity is always to be preferred to brevity. Let me point you to Justin Etheredge's essay "Don't be clever" (<a href="http://www.codethinked.com/dont-be-clever" class="">http://www.codethinked.com/dont-be-clever</a>). </div><div style="font-size: 16px;" class=""><br class=""></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><span style="color: rgb(85, 85, 85); font-family: Georgia; font-size: 20px; text-align: justify;" class="">So next time you go to write a super clever line of code, think to yourself "Will the benefits of this super cleverness be outweighed by the future issues in maintaining and understanding the code?" And if there is </span><strong style="margin: 0px; padding: 0px; border: 0px; outline: 0px; font-size: 20px; vertical-align: baseline; color: rgb(85, 85, 85); font-family: Georgia; text-align: justify;" class="">any</strong><span style="color: rgb(85, 85, 85); font-family: Georgia; font-size: 20px; text-align: justify;" class="">hesitation at all, then you better not be clever, because 3 months from now you will come across that code and say "What the hell was I thinking?" Then you’ll end up rewriting it anyway.</span></div></blockquote><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><b class="">Incrementor Challenges</b></div><div style="font-size: 16px;" class=""><b class=""><br class=""></b></div><div style="font-size: 16px;" class="">Another complaint involved forgetting or misplacing the incrementor when transforming items to while loops. There are two cases being glommed together here, and I'd like to separate them.</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">First, there's a collection case, in which the collection provides its own indices. In such implementations, there's simply no need to manually declare and manage an index. You can use for-in.</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">Second, there's what I'm going to call the bitmap case, where an index may refer to geometrically-related indices, which happens often in image processing. (I'm going to repress any "Just use Accelerate" rant. This is a significant area of programming). Here's some pseudocode that demonstrates how this might look in a for-loop-less Swift implementation:</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><div class=""><font face="Courier" class=""> for row in 0..<height {</font></div><div class=""><span style="font-family: Courier;" class=""> for column in 0..<width {</span></div><div class=""><font face="Courier" class=""> var sum: UInt = 0</font></div><div class=""><font face="Courier" class=""> for rowOffset in -1...1 {</font></div><div class=""><font face="Courier" class=""> for columnOffset in -1...1 {</font></div><div class=""><font face="Courier" class=""> let index = pixelOffsetAt(</font><span style="font-family: Courier;" class="">row + rowOffset, column + columnOffset) </span><span style="font-family: Courier;" class="">+ redChannelOffset</span></div><div class=""><span style="font-family: Courier;" class=""> sum += pixels[index]</span></div><div class=""><font face="Courier" class=""> }</font></div><div class=""><font face="Courier" class=""> }</font></div><div class=""><font face="Courier" class=""> let currentRedPixelBlurredAverage = sum / 9</font></div><div class=""><font face="Courier" class=""> // blah blah other stuff</font></div><div class=""><font face="Courier" class=""> }</font></div><div class=""><font face="Courier" class=""> }</font></div></div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">Again, I don't see anything that would limit relative indexing with this proposal.</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><b class="">The Skip Case</b></div><div style="font-size: 16px;" class=""><b class=""><br class=""></b></div><div style="font-size: 16px;" class="">Matthijs Hollemans writes, </div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><br class=""></div><div class=""><div class="" style="font-family: Palatino-Roman;">Another benefit of a C-style for loop is that it simply ignores the loop when n <= i, as in the following example,</div><div class="" style="font-family: Palatino-Roman;"><br class=""></div><div class="" style="font-family: Palatino-Roman;"><div class="" style="margin: 0px; font-size: 18px; font-family: Inconsolata;"><span class="" style="color: rgb(187, 44, 162);"> for</span> <span class="" style="color: rgb(187, 44, 162);">var</span> i = <span class="" style="color: rgb(39, 42, 216);">100</span>; i < <span class="" style="color: rgb(79, 129, 135);">n</span>; ++i { ...</div><div class="" style="margin: 0px; font-size: 18px; font-family: Inconsolata;"><br class=""></div><div class="" style="margin: 0px; font-size: 18px; font-family: Inconsolata; min-height: 17px;"><span class="" style="font-family: Helvetica; font-size: 14px;">while the Swifty version gives an error because it cannot create a range where the end is smaller than the start: </span></div><div class="" style="margin: 0px; font-size: 18px; font-family: Inconsolata; min-height: 17px;"><br class=""></div><div class="" style="margin: 0px; font-size: 18px; font-family: Inconsolata;"><span class="" style="color: rgb(187, 44, 162);"> for</span> i <span class="" style="color: rgb(187, 44, 162);">in</span> <span class="" style="color: rgb(39, 42, 216);">100</span>..<<span class="" style="color: rgb(79, 129, 135);">n</span> { ...</div><div class="" style="margin: 0px; font-size: 18px; font-family: Inconsolata;"><br class=""></div></div><div class="" style="font-family: Palatino-Roman;">Of course, you can add an if-statement to catch this but in the C-style loop this is implicit. Hence, it is more expressive.</div></div><div class="" style="font-family: Palatino-Roman;"><br class=""></div></blockquote><font face="Palatino-Roman" style="font-size: 16px;" class="">I may be in the minority but I rather like that this becomes an error. The "skip" behavior reads to me as an unintended side-effect rather than a purposeful design goal. I prefer a philosophy that minimizes such possibilities in a safe modern language.<br class=""></font><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><b class="">Issues of Type </b></div><div style="font-size: 16px;" class=""><b class=""><br class=""></b></div><div style="font-size: 16px;" class="">Roland King writes,</div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><br class=""></div><div class=""><span style="font-family: Palatino-Roman;" class="">I must be the only person who still likes C-style for loops on occasion. eg a loop with something floating point </span></div></blockquote><font face="Palatino-Roman" style="font-size: 16px;" class=""><div class=""><font face="Palatino-Roman" class=""><br class=""></font></div>I counter that stride addresses this for all conforming strideable types, not just floating point values. <br class=""></font><div style="font-size: 16px;" class=""><b class=""><br class=""></b></div><div style="font-size: 16px;" class=""><b class="">Training Costs and Migration Benefits</b></div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">The main argument against losing the feature seems to be the higher training costs for C-style coders and the higher porting costs for existing C-code. I'd argue that the training costs to a new language are significant and whether there's a C-style for loop will not materially change those overall costs, especially for those moving from Objective-C where the for-in loop is common. Second, porting to Swift should be motivated by an enhancement of safety and maintainability. Swift already supports external calls to C routines. If you want to keep your code in C, there's nothing stopping you from doing so. (Or to put it in American Politician-speak, "If you like your C-code, you can keep your C-code")</div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class=""><b class="">More Direct Swift Replacements</b></div><div style="font-size: 16px;" class=""><br class=""></div><div style="font-size: 16px;" class="">After all this discussion, let me end with a suggestion proposed by Joe Groff for anyone who would still miss the for-loop by approximating the same control flow in native Swift:</div><div style="font-size: 16px;" class=""><br class=""></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class=""><br class=""></div><div class=""><div class="" style="font-family: Palatino-Roman;">func cStyleFor(@autoclosure init initializer: () -> (), @autoclosure test: () -> Bool, @autoclosure inc: () -> (), body: () throws -> ()) rethrows {</div><div class="" style="font-family: Palatino-Roman;"> // left as an exercise</div><div class="" style="font-family: Palatino-Roman;">}</div><div class="" style="font-family: Palatino-Roman;"><br class=""></div><div class="" style="font-family: Palatino-Roman;">var i = 0</div><div class="" style="font-family: Palatino-Roman;">cStyleFor(init: i = 0, test: i < 10, inc: ++i) {</div><div class="" style="font-family: Palatino-Roman;"> print(i)</div><div class="" style="font-family: Palatino-Roman;">}</div><div class="" style="font-family: Palatino-Roman;"><br class=""></div><div class="" style="font-family: Palatino-Roman;">-Joe</div></div><div class="" style="font-family: Palatino-Roman;"><br class=""></div></blockquote><font face="Palatino-Roman" size="3" class="">The only feature this does not include, as pointed out by list members, is a co-declared variable binding. In a C-style for-loop, the "i" is bound as part of the declaration. In this implementation, it requires a separate declaration line and remains in the scope for its lifetime.<br class=""></font><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px; font-size: 16px;" class=""><div class="" style="font-family: Palatino-Roman;"><br class=""></div></blockquote><font face="Palatino-Roman" style="font-size: 16px;" class=""><b class="">Wrap-up</b></font><div style="font-size: 16px;" class=""><font face="Palatino-Roman" class=""><b class=""><br class=""></b></font></div><div style="font-size: 16px;" class=""><font face="Palatino-Roman" class="">I hope I have addressed the concerns brought up on-list. If I missed one of yours please feel free to reply. The voting and review period will be between 7 Dec and 10 Dec. Here is the master schedule: <a href="https://github.com/apple/swift-evolution/blob/master/schedule.md" class="">https://github.com/apple/swift-evolution/blob/master/schedule.md</a></font></div><div style="font-size: 16px;" class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div style="font-size: 16px;" class=""><font face="Palatino-Roman" class="">Best regards,</font></div><div style="font-size: 16px;" class=""><font face="Palatino-Roman" class=""><br class=""></font></div><div style="font-size: 16px;" class=""><font face="Palatino-Roman" class="">-- Erica</font></div><div class=""><font face="Palatino-Roman" style="font-size: 16px;" class=""><br class=""></font><div style="font-size: 16px;" class=""><br class=""></div><br style="font-size: 16px;" class=""><div style="font-size: 16px;"><blockquote type="cite" class=""><div class="">On Dec 6, 2015, at 7:47 AM, J. Cheyo Jimenez 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 class=""><br class=""></div><div class=""><a href="https://github.com/apple/swift/commit/0d001480a94f975355cd458973d5c51cef55bff1" class="">https://github.com/apple/swift/commit/0d001480a94f975355cd458973d5c51cef55bff1</a><br class=""><br class="">On Sunday, December 6, 2015, Clemens Wagner via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> We’ve developed a number of Swift apps for various clients over the past year and have not needed C style for loops either.<br class="">
<br class="">
But I think this is a very weak reason for *removing* any portion like C-loops and increment or decrement operators of a programming language. How about the developers and the productive code which used C-style loops already?<br class="">
<br class="">
I understand the reasons why you, Erica and the others don’t like C-style loops. But changing the philosophy of a productive programming language is a very bad idea.<br class="">
<br class="">
Cheers<br class="">
Clemens<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="javascript:;" onclick="_e(event, 'cvml', 'swift-evolution@swift.org')" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=r5jpKsi6nat7oa43lpCLi5GRGm2utDkbDscuFklXZ2dCsXxbkitKACRb-2FuTcz-2F9h8C8fwAkzcFgSZsSni5aYcivsyNwLhtHLN0TDPODDQmWhB3Par3ISvvtQcqUkrcjijGXOF-2BmewWoeB73D9pQf0Ye9re8FM-2Fmj6Wa-2FcpKOMDeT0tYWR8qZ-2BnZrmE7UhVC80X0d-2Fww8h5eUpHM0JrWVKlMD4joZql0mI9Lx6kKOchY-3D" alt="" width="1" height="1" border="0" style="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;" class="">
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>