<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><span></span></div><div><div></div><div>+1 for keeping forEach and the rationale.</div><div><br></div><div>-Thorsten </div><div><br>Am 08.12.2015 um 22:56 schrieb Erica Sadun via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8">I'd prefer retain `for-each`. I like it as a natural termination step for functional chaining. Here's what I wrote about the topic when it first appeared. There are bits of the discussion that I'd refine since I first wrote this but I decided it was easier to paste this as a whole and save my afternoon.<div class=""><br class=""></div><div class="">-- E</div><div class=""><div class=""><br class=""></div><div class=""><p style="box-sizing: border-box; font-size: 17px; margin: 15px 0px; zoom: 1; color: rgb(5, 0, 0); font-family: Georgia, serif;" class=""><strong style="box-sizing: border-box;" class="">ForEach:</strong> Just when I finally got around to implementing this generically:</p><pre style="box-sizing: border-box; border-style: solid; border-color: rgb(5, 0, 0); border-width: 2px 0px; padding: 15px 0px; font-family: 'andale mono', 'lucida console', monospace; font-size: 0.75em; white-space: pre-wrap; word-wrap: break-word; width: 859.03125px; margin-top: 30px; margin-bottom: 30px; margin-left: 40px; color: rgb(5, 0, 0);" class="">public extension SequenceType {
func mapDo(p: (Self.Generator.Element) -> Void) {
for x in self {p(x)}
}
}</pre><p style="box-sizing: border-box; font-size: 17px; margin: 15px 0px; zoom: 1; color: rgb(5, 0, 0); font-family: Georgia, serif;" class="">Apple introduced forEach.</p><pre style="box-sizing: border-box; border-style: solid; border-color: rgb(5, 0, 0); border-width: 2px 0px; padding: 15px 0px; font-family: 'andale mono', 'lucida console', monospace; font-size: 0.75em; white-space: pre-wrap; word-wrap: break-word; width: 859.03125px; margin-top: 30px; margin-bottom: 30px; margin-left: 40px; color: rgb(5, 0, 0);" class="">Array(1...5).map({$0 * 2}).forEach{print($0)}</pre><p style="box-sizing: border-box; font-size: 17px; margin: 15px 0px; zoom: 1; color: rgb(5, 0, 0); font-family: Georgia, serif;" class="">You use this procedurally when you don’t collect/return the results. Notice how I’ve followed the <a href="http://twitter.com/Eridius" style="box-sizing: border-box; color: rgb(234, 0, 0); text-decoration: none;" class="">Rule-of-Kevin-Ballard</a> above. No parens around the braces because the closure is procedural.</p><pre style="box-sizing: border-box; border-style: solid; border-color: rgb(5, 0, 0); border-width: 2px 0px; padding: 15px 0px; font-family: 'andale mono', 'lucida console', monospace; font-size: 0.75em; white-space: pre-wrap; word-wrap: break-word; width: 859.03125px; margin-top: 30px; margin-bottom: 30px; margin-left: 40px; color: rgb(5, 0, 0);" class="">public func forEach(@noescape body: (Self.Generator.Element) -> ())</pre><p style="box-sizing: border-box; font-size: 17px; margin: 15px 0px; zoom: 1; color: rgb(5, 0, 0); font-family: Georgia, serif;" class="">This new language feature eliminates the awkward “for _ in” construct and provides a procedural end-point for functional chains. If you want to continue the chain (for example if you want to throw a print($0) in the middle) continue using <em style="box-sizing: border-box;" class="">map</em>, which offers pass-through.</p><p style="box-sizing: border-box; font-size: 17px; margin: 15px 0px; zoom: 1; color: rgb(5, 0, 0); font-family: Georgia, serif;" class="">Apple’s pointers:</p><ul style="box-sizing: border-box; padding: 0px; margin: 15px 0px 15px 40px; list-style-position: initial; list-style-image: initial; color: rgb(5, 0, 0); font-family: Georgia, serif; font-size: 17px;" class=""><li style="box-sizing: border-box; margin: 10px 0px;" class=""><em style="box-sizing: border-box;" class="">Unlike for-in loops, you can’t use break or continue to exit the current call of the body closure or skip subsequent calls. </em></li><li style="box-sizing: border-box; margin: 10px 0px;" class=""><em style="box-sizing: border-box;" class="">Also unlike for-in loops, using return in the body closure will only exit from the current call to the closure, not any outer scope, and won’t skip subsequent calls. </em></li><li style="box-sizing: border-box; margin: 10px 0px;" class=""><em style="box-sizing: border-box;" class="">Due to these limitations, the forEach member is only recommended when applied to a chained series of functional algorithms (e.g. foo.map {…}.filter {… }.forEach { …}) and when the body is small. In other cases, we recommend using the for..in statement. (18231840)</em></li></ul><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 8, 2015, at 1:28 PM, Kevin Kachikian 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="">I support keeping forEach in. I use it enough myself. It also makes it easier for beginning Swift programmers to understand syntactically.<br class=""><br class="">Kevin<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Dec 8, 2015, at 12:21 PM, Sean Heber via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">It’d probably be confusing without a new keyword or symbol, but in the case of @noescape closures, maybe “return" could return from the outer scope instead of the inner one. Smalltalk has a distinction kind of like this.<br class=""><br class="">In some ways, I think “return” should be reserved for actually returning from a *function* and “^” or something could exist for returning from a *closure* and that distinction would eliminate strange nested returns that sometimes crop up in these scenarios.<br class=""><br class="">So as written, your example would just do the “right thing” if “return” was so defined. If you wanted to explicitly do the wrong thing, it could be written as:<br class=""><br class=""> func indexOf_foreach(element: Element) -> Int? {<br class=""> self.indices.filter { idx in self[idx] == element }.forEach { idx in<br class=""> ^ idx<br class=""> }<br class=""> return nil<br class=""> }<br class=""><br class="">If you tried to use “return” in an escaping closure, then it could be an error.<br class=""><br class="">l8r<br class="">Sean<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Dec 8, 2015, at 1:07 PM, Chris Eidhof via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">Hi all,<br class=""><br class="">As long as the `for` loop is in the language, I don’t really see the use of `forEach`. I understand that it can read much nicer to write something like `a.map { something }.filter { somethingElse }.forEach {` rather than a `for` loop. However, I think the costs don’t outweigh the benefits. It might look like a for loop can just be replaced by a `forEach`, however, this is not true in the general case. For example, consider the following example:<br class=""><br class=""> func indexOf_foreach(element: Element) -> Int? {<br class=""> self.indices.filter { idx in self[idx] == element }.forEach { idx in<br class=""> return idx<br class=""> }<br class=""> return nil<br class=""> }<br class=""><br class="">The code above (I realise it’s quite inefficient) might look like it’s returning the first index for which the filter’s condition returned true. However, the first occurrence of return is actually returning inside the closure, not the outer function. So the result of this function is always nil.<br class=""><br class="">Another solution would be to give a good warning/error message here (you’re trying to return an Optional value where we expect a ()). However, this is also problematic when dealing with side-effects. For example:<br class=""><br class="">[1,2,3,4,5].forEach { num in<br class=""> print(num)<br class=""> if num > 3 { return }<br class="">}<br class=""><br class="">I think it’s quite easy to get things wrong with forEach, so I’d propose removing it and rather having a regular for loop. (Erica-style).<br class=""><br class="">Chris<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></div></blockquote></div><br class=""></div></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=Z0lfE0AvBRKWSDAcltP5-2FwA6tH7CtZqjBw6KQdxzh8UeEAuMESPncyStoaIO7wH-2B1NcBsSDwHKDZK7LHlAi2Lan4LGF21A8EI06UAtHd9rcgO472j9SDuhYfZCQUgxdDqFbkFTdKMn2MIh0hq5511qogREwYR-2FxiBa-2BN2Y1e9siBP0U7q8yamVNMfuIMJdLdygiU5qjvd9yZDaEXNuTHSi7XN-2FEo34igIXgUNDKrUomc0YHbSRo3tX3sXTtN0ML9" 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;">
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></body></html>