<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 class=""><br class=""></div><div class="">The original example contains a bug which is present on all looping version/alternative due to the mutating nature of the array. Using the zip implementation:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> array = [ <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">""</span>, <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"a"</span>, <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"b"</span>, <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"c"</span>, <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">""</span>, <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"d"</span> ]</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> secondHalf = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">array</span>[<span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">array</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">count</span>/<span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">2</span>..&lt;<span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">array</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">count</span>]</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">for</span> (index, element) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> <span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">zip</span>(<span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">secondHalf</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">indices</span>, <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">secondHalf</span>) {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">if</span> element == <span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">""</span> {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">secondHalf</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">removeAtIndex</span>(index)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div><div class=""><br class=""></div><div class="">The variable index cycles through 3,4 and 5; but in order to be able to remove the right element beyond the first removal, the variable index should have cycled through 3, 4 and 4 (as some elements got shifted after the first mutation). Mutating the array/list which one loops over is a risky business and is a nice source of bugs (including infinite loop). If this (Index, Element) is further investigated, it should consider that one may also want to do a insert(:atIndex:), and may expect the (Index, Element) to have proper Index but only for the original Element.</div><div class=""><br class=""></div><div class="">Dany St-Amant</div><div class=""><br class=""></div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class="">Le 28 déc. 2015 à 01:06, Kevin Ballard via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class="">


<title class=""></title>

<div class=""><div class="">What you're asking for can already be done with `zip(col.indices, col)`. And in my experience the need for this sort of thing is rare enough that there's no need to have a dedicated property for it in the stdlib. The few times that I've needed this sort of thing, I've always just said<br class=""></div>
<div class="">&nbsp;</div>
<div class="">for index in col.indices {<br class=""></div>
<div class="">&nbsp; &nbsp; let elt = col[index]<br class=""></div>
<div class="">&nbsp; &nbsp; // ...<br class=""></div>
<div class="">}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">and that's pretty simple. But if I ever did need to map it, I'd just use the aforementioned zip() expression.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">-Kevin Ballard<br class=""></div>
<div class="">&nbsp;</div>
<div class="">On Sun, Dec 27, 2015, at 12:08 AM, Patrick Pijnappel via swift-evolution wrote:<br class=""></div>
<blockquote type="cite" class=""><div dir="ltr" class=""><div class="">-- Introduction<br class=""></div>
<div class="">&nbsp;</div>
<div class="">There should be a property on CollectionType that returns a sequence of (Index, Element) tuples.<br class=""></div>
<div class="">Currently&nbsp;<span class="font" style="font-family:monospace, monospace">enumerate()</span>&nbsp;is often used instead, but it is not well suited to the task and can lead to bugs.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">-- Motivation<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Using&nbsp;<span class="font" style="font-family:monospace, monospace">enumerate()</span>&nbsp;instead of an <span class="font" style="font-family:monospace, ' monospace'">(Index, Element)</span> sequence has two main problems.<br class=""></div>
<div class="">Both arise because&nbsp;<span class="font" style="font-family:monospace, monospace">enumerate()</span>&nbsp;returns a sequence of <span class="font" style="font-family:monospace, ' monospace'">(n, Element)</span> tuples,<br class=""></div>
<div class="">where n is the element *number*, instead of a sequence of <span class="font" style="font-family:monospace, ' monospace'">(Index, Element)</span>.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">1) It doesn't work for collections&nbsp;not indexed by integers.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">2) It doesn't do what you might expect in some cases, as indices do not always start at 0.<br class=""></div>
<div class="">For example <span class="font" style="font-family:monospace, ' monospace'">ArraySlice's</span>&nbsp;indices do not:&nbsp;<span class="font" style="font-family:monospace, ' monospace'">array[2..&lt;5]</span> starts with index 2.<br class=""></div>
<div class="">Consider the following code to take the 2nd half of the array and remove all empty elements:<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">var array = [ "", "a", "b", "c", "", "d" ]</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">var secondHalf = array[array.count/2..&lt;array.count]</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">for (index, element) in secondHalf.enumerate() {</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'"><span style="white-space:pre;" class=""></span>if element == "" {</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'"><span style="white-space:pre;" class=""></span>secondHalf.removeAtIndex(index)</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'"><span style="white-space:pre;" class=""></span>}</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">}</span><br class=""></div>
<div class="">&nbsp;</div>
<div class="">This code will crash (ignoring for a moment this should probably be using filter).<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">-- Alternatives<br class=""></div>
<div class="">&nbsp;</div>
<div class="">The same effect can already be achieved using the following:<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">for index in collection.indices {</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">&nbsp; let element = collection[index]</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">&nbsp; // ...</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">}</span><br class=""></div>
<div class="">&nbsp;</div>
<div class="">However having a dedicated <span class="font" style="font-family:monospace, ' monospace'">(Index, Element)</span> sequence has the following advantages:<br class=""></div>
<div class="">a) It can help prevent people from using&nbsp;<span class="font" style="font-family:monospace, monospace">enumerate()</span>&nbsp;inappropriately.<br class=""></div>
<div class="">b) It is very common use case that deserves shortening.<br class=""></div>
<div class="">c) It can be chained (e.g. to map).<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">-- Proposed Solution<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Add a property/method on <span class="font" style="font-family:monospace, ' monospace'">CollectionType</span> that returns a sequence of <span class="font" style="font-family:monospace, ' monospace'">(Index, Element)</span> tuples.<br class=""></div>
<div class="">For example, using a property named <span class="font" style="font-family:monospace, ' monospace'">indexed</span>:<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">for (index, element) in collection.indexed {</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">&nbsp; // ...</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">}</span><br class=""></div>
<div class="">&nbsp;</div>
<div class="">This should be the preferred idiom when you want both the index and the element.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Note that <span class="font" style="font-family:monospace, ' monospace'">enumerate()</span> does still have valid roles to play:<br class=""></div>
<div class="">- When you actually do want the element number, not the index.<br class=""></div>
<div class="">- When you have a <span class="font" style="font-family:monospace, ' monospace'">SequenceType</span>, as it isn't indexed.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">-- Implementation<br class=""></div>
<div class="">&nbsp;</div>
<div class="">The feature could be entirely implemented using existing constructs:<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">extension CollectionType {</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">&nbsp; var indexed: AnySequence&lt;(Index, Generator.Element)&gt; {</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">&nbsp; &nbsp; return AnySequence(indices.lazy.map { ($0, self[$0]) })</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">&nbsp; }</span><br class=""></div>
<div class=""><span class="font" style="font-family:monospace, ' monospace'">}</span><br class=""></div>
<div class="">&nbsp;</div>
<div class="">Alternatively, a dedicated <span class="font" style="font-family:monospace, ' monospace'">SequenceType</span> and/or <span class="font" style="font-family:monospace, ' monospace'">GeneratorType</span> could be added.<br class=""></div>
<div class="">&nbsp;</div>
</div>
<div class=""><img style="height:1px !important;width:1px !important;border-top-width:0px !important;border-right-width:0px !important;border-bottom-width:0px !important;border-left-width:0px !important;margin-top:0px !important;margin-bottom:0px !important;margin-right:0px !important;margin-left:0px !important;padding-top:0px !important;padding-bottom:0px !important;padding-right:0px !important;padding-left:0px !important;" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/981667c5fa75d2d6102189c7105ad9f6333023a0ad47163c7ff20e76523c1159/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e43694d61464360346d4a727a7d2232443234316973476151574438767a54603e48717739376a58567554664f4a72367a44615c4a49454c6a40354663527463593450736531625351473833695b4377335f43657b473c65366e4f496a4468616935613875637057626d22324872535d2236455d4645414c417e676d43446755785945323468707b695a6a6b6777703b416c6f4a465969363a72463231534f657034707a54663135675144607d22364e673154766843667a63325259395256494036533a4a44394155476d23344d23344/open" class=""><br class=""></div>
<div class=""><u class="">_______________________________________________</u><br class=""></div>
<div class="">swift-evolution mailing list<br class=""></div>
<div class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""></div>
<div class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div>
</blockquote><div class="">&nbsp;</div>

<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=TWMs2ohk0-2BcrwF6GNUK35QNQ48G65bEqXMjRx145i-2BK2pBNfaH-2FaV6xYo7A2ZGuv6y05Zgh5-2B87u-2BAA1jX4EuE0S5zhsyNm-2B-2By-2FD-2FBj1p4R3JXTyyzq8d1XT0hkcyKsYJ1fBV8I3RM6Yd3Z9sgHTmIBjgtoGN34NTzqVxJY7CXtp4k2m-2BK7vwQ5Xw-2B2zkiH7tIMHv-2BFMAW4cFA4k8JiCFFlM568Cs0e5Q2DE-2B6K2bR4-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=""></body></html>