<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="">In most programming languages, map does not have any side-effect. This is may be the reason forEach was added.<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 30, 2015, at 2:10 PM, Howard Lovatt via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><span class=""></span></div><div class=""><span class="">You could replace `forEach` with a supped up `map` that also allowed `break` and `continue`. The following&nbsp;</span><font class="" style="background-color: rgba(255, 255, 255, 0);">library function gives `continue` and `break` and also combines `repeat`,&nbsp;`times`, `forEach`, `filter`, `flatMap`, and `map` into one:</font><div class=""><font class="" style="background-color: rgba(255, 255, 255, 0);"><br class=""></font><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">public</span>&nbsp;<span class="">final</span>&nbsp;<span class="">class</span>&nbsp;MapController&lt;E, R&gt; {</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">var</span>&nbsp;results = [R]()</span></div><p class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp;&nbsp; &nbsp;</span><br class="webkit-block-placeholder"></p><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">var</span>&nbsp;isContinuing =&nbsp;<span class="">true</span></span></div><p class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp;&nbsp; &nbsp;</span><br class="webkit-block-placeholder"></p><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">init</span>&lt;C: CollectionType&nbsp;<span class="">where</span>&nbsp;C.Generator.Element == E&gt;(<span class="">_</span>&nbsp;collection: C, sizeEstimate: Int =&nbsp;<span class="">0</span>,&nbsp;<span class="">@noescape</span>&nbsp;mapper: (controller: MapController&lt;E, R&gt;, element: E)&nbsp;<span class="">throws</span>&nbsp;-&gt; R?)&nbsp;<span class="">rethrows</span>&nbsp;{</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp; results.reserveCapacity(sizeEstimate)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="">for</span>&nbsp;<span class="">var</span>&nbsp;generator = collection.generate(), element = generator.next(); element !=&nbsp;<span class="">nil</span>&nbsp;&amp;&amp; isContinuing; element = generator.next() {</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="">let</span>&nbsp;result =&nbsp;<span class="">try</span>&nbsp;mapper(controller:&nbsp;<span class="">self</span>, element: element!)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="">if</span>&nbsp;<span class="">let</span>&nbsp;actualResult = result {</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; results.append(actualResult)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; }</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">extension</span><span class="">&nbsp;</span>CollectionType<span class="">&nbsp;{</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span>/// Controllable `map`, additional controls beyond simple `map` are:</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">///</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span>/// &nbsp; 1. Continue without returning a result (`return nil`)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span>/// &nbsp; 2. Return multiple results (`control.results += [...]` then `return nil`)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span>/// &nbsp; 3. Break (`control.isContinuing = false` then `return nil`)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">///</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span>/// These additional controls allow this `map` to function like `repeat`, `times`, `forEach`, `filter`, `flatMap`, and `map` combined into one as well as providing an early termination (break).</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">@warn_unused_result</span>&nbsp;<span class="">func</span>&nbsp;map&lt;R&gt;(sizeEstimate sizeEstimate: Int =&nbsp;<span class="">0</span>,&nbsp;<span class="">@noescape</span>&nbsp;mapper: (controller: MapController&lt;<span class="">Self</span>.Generator.Element, R&gt;, element:&nbsp;<span class="">Self</span>.Generator.Element)&nbsp;<span class="">throws</span>&nbsp;-&gt; R?)&nbsp;<span class="">rethrows</span>&nbsp;-&gt; [<span class="">R</span>] {</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="">return</span>&nbsp;<span class="">try</span>&nbsp;MapController(<span class="">self</span>, sizeEstimate: sizeEstimate, mapper: mapper).results</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; }</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">// Demonstration of full functionality including continue, break, and multiple returns</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">var</span>&nbsp;result = (<span class="">0</span>&nbsp;..&lt;&nbsp;<span class="">5</span>).map { (control, index) -&gt;&nbsp;<span class="">Int</span>?&nbsp;<span class="">in</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">switch</span>&nbsp;index {</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">case</span>&nbsp;<span class="">1</span>:</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span class="">return</span><span class="">&nbsp;</span><span class="">nil</span><span class="">&nbsp;</span>// Continue - skip 1 (`filter`)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">case</span>&nbsp;<span class="">2</span>:</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp; control.results.append(</span><span class="">2</span><span class="">)&nbsp;</span>// Yield two results - this one and the 'return’ yield (`flatMap`)</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp;&nbsp;<span class="">case</span>&nbsp;<span class="">3</span>:</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp; control.isContinuing =&nbsp;</span><span class="">false</span><span class="">&nbsp;</span>// Break after next yield - which could be `return nil` if there are no more results</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span>default<span class="">:</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="">break</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; }</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span><span class="">return</span><span class="">&nbsp;index&nbsp;</span>// Yield next result - except for case 1 all the above yield `index`</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">print(result)&nbsp;</span>// prints `[0, 2, 2, 3]` note missing "1", double "2", and last is "3"</span></div><div class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">// Demonstration of `repeat`/`forEach`/`times` like usage - note `(_, _) -&gt; Void?`</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">result = [Int]()</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">(<span class="">0</span>&nbsp;..&lt;&nbsp;<span class="">3</span>).map { (<span class="">_</span>,&nbsp;<span class="">_</span>) -&gt;&nbsp;<span class="">Void</span>?&nbsp;<span class="">in</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">&nbsp; &nbsp; result.append(<span class="">1</span>)&nbsp;<span class="">// Do whatever - in this case append to a global</span></span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">&nbsp; &nbsp;&nbsp;</span><span class="">return</span><span class="">&nbsp;</span><span class="">nil</span><span class="">&nbsp;</span>// Don't yield any results</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class="" style="margin: 0px; line-height: normal;"><span style="background-color: rgba(255, 255, 255, 0);" class=""><span class="">print(result)&nbsp;</span>// prints `[1, 1, 1]`</span></div></blockquote><font class="" style="background-color: rgba(255, 255, 255, 0);"><br class=""></font></div><div class=""><font class="" style="background-color: rgba(255, 255, 255, 0);">Would this be a superior alternative to both `forEach` and `times` in the library and `repeat` as a language feature?</font></div><span class=""></span><br class=""><span class="">Sent from my iPad</span></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=AdkfTiApI80cNEyortTzHb2fcfA247JB3qOAr5hAOEH4QfJLAaMHqR9-2F73u1HcU5UvYftXFz6Rs-2B0sjZJfOAonVd6RgRNHj2T-2BmfdCi45PGAS85R1S7kbyOe7qPd5vSubNU1iKO0oRxcZH-2F4u88CEtmJzYw2aIofPSjz-2BftW9NQq-2BOOvm0So4r7lHO6-2Bd-2BML5DcuoGtUCUYQh5HF7NxPIQ-3D-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="">
</div>
_______________________________________________<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>