<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div>What you describe isn't a bug in the implementation, it's a bug in the expectation that you can mutate an array that you're iterating over. With any other collection, the mutation would actually invalidate the index. It so happens that Arrays use Int as their index, so they can't really be considered invalid, but you should treat them the same way in cases like this; mutating the array means the index range you're iterating over is no longer representative of the array.<br></div>
<div>&nbsp;</div>
<div>-Kevin Ballard</div>
<div>&nbsp;</div>
<div>On Mon, Dec 28, 2015, at 06:30 PM, Dany St-Amant via swift-evolution wrote:<br></div>
<blockquote type="cite"><div>&nbsp;</div>
<div>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:<br></div>
<div>&nbsp;</div>
<div><div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(187, 44, 162)">var</span> array = [ <span class="colour" style="color:rgb(209, 47, 27)">""</span>, <span class="colour" style="color:rgb(209, 47, 27)">"a"</span>, <span class="colour" style="color:rgb(209, 47, 27)">"b"</span>, <span class="colour" style="color:rgb(209, 47, 27)">"c"</span>, <span class="colour" style="color:rgb(209, 47, 27)">""</span>, <span class="colour" style="color:rgb(209, 47, 27)">"d"</span> ]<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(187, 44, 162)">var</span> secondHalf = <span class="colour" style="color:rgb(79, 129, 135)">array</span>[<span class="colour" style="color:rgb(79, 129, 135)">array</span>.<span class="colour" style="color:rgb(112, 61, 170)">count</span>/<span class="colour" style="color:rgb(39, 42, 216)">2</span>..&lt;<span class="colour" style="color:rgb(79, 129, 135)">array</span>.<span class="colour" style="color:rgb(112, 61, 170)">count</span>]<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(187, 44, 162)">for</span> (index, element) <span class="colour" style="color:rgb(187, 44, 162)">in</span> <span class="colour" style="color:rgb(61, 29, 129)">zip</span>(<span class="colour" style="color:rgb(79, 129, 135)">secondHalf</span>.<span class="colour" style="color:rgb(112, 61, 170)">indices</span>, <span class="colour" style="color:rgb(79, 129, 135)">secondHalf</span>) {<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(187, 44, 162)">if</span> element == <span class="colour" style="color:rgb(209, 47, 27)">""</span> {<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;"><span class="colour" style="color:rgb(79, 129, 135)">secondHalf</span>.<span class="colour" style="color:rgb(61, 29, 129)">removeAtIndex</span>(index)<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;">&nbsp; &nbsp; }<br></div>
<div style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:11px;line-height:normal;font-family:Menlo;">}<br></div>
</div>
<div>&nbsp;</div>
<div>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.<br></div>
<div>&nbsp;</div>
<div>Dany St-Amant<br></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><blockquote type="cite"><div>Le 28 déc. 2015 à 01:06, Kevin Ballard via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; a écrit :<br></div>
<div>&nbsp;</div>
<div><div><div>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></div>
<div>&nbsp;</div>
<div>for index in col.indices {<br></div>
<div>&nbsp; &nbsp; let elt = col[index]<br></div>
<div>&nbsp; &nbsp; // ...<br></div>
<div>}<br></div>
<div>&nbsp;</div>
<div>and that's pretty simple. But if I ever did need to map it, I'd just use the aforementioned zip() expression.<br></div>
<div>&nbsp;</div>
<div>-Kevin Ballard<br></div>
<div>&nbsp;</div>
<div>On Sun, Dec 27, 2015, at 12:08 AM, Patrick Pijnappel via swift-evolution wrote:<br></div>
<blockquote type="cite"><div dir="ltr"><div>-- Introduction<br></div>
<div>&nbsp;</div>
<div>There should be a property on CollectionType that returns a sequence of (Index, Element) tuples.<br></div>
<div>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></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>-- Motivation<br></div>
<div>&nbsp;</div>
<div>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></div>
<div>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></div>
<div>where n is the element *number*, instead of a sequence of <span class="font" style="font-family:monospace, ' monospace'">(Index, Element)</span>.<br></div>
<div>&nbsp;</div>
<div>1) It doesn't work for collections&nbsp;not indexed by integers.<br></div>
<div>&nbsp;</div>
<div>2) It doesn't do what you might expect in some cases, as indices do not always start at 0.<br></div>
<div>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></div>
<div>Consider the following code to take the 2nd half of the array and remove all empty elements:<br></div>
<div>&nbsp;</div>
<div><span class="font" style="font-family:monospace, ' monospace'">var array = [ "", "a", "b", "c", "", "d" ]</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">var secondHalf = array[array.count/2..&lt;array.count]</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">for (index, element) in secondHalf.enumerate() {</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'"><span style="white-space:pre;"></span>if element == "" {</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'"><span style="white-space:pre;"></span>secondHalf.removeAtIndex(index)</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'"><span style="white-space:pre;"></span>}</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">}</span><br></div>
<div>&nbsp;</div>
<div>This code will crash (ignoring for a moment this should probably be using filter).<br></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>-- Alternatives<br></div>
<div>&nbsp;</div>
<div>The same effect can already be achieved using the following:<br></div>
<div>&nbsp;</div>
<div><span class="font" style="font-family:monospace, ' monospace'">for index in collection.indices {</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">&nbsp; let element = collection[index]</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">&nbsp; // ...</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">}</span><br></div>
<div>&nbsp;</div>
<div>However having a dedicated <span class="font" style="font-family:monospace, ' monospace'">(Index, Element)</span> sequence has the following advantages:<br></div>
<div>a) It can help prevent people from using&nbsp;<span class="font" style="font-family:monospace, monospace">enumerate()</span>&nbsp;inappropriately.<br></div>
<div>b) It is very common use case that deserves shortening.<br></div>
<div>c) It can be chained (e.g. to map).<br></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>-- Proposed Solution<br></div>
<div>&nbsp;</div>
<div>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></div>
<div>For example, using a property named <span class="font" style="font-family:monospace, ' monospace'">indexed</span>:<br></div>
<div>&nbsp;</div>
<div><span class="font" style="font-family:monospace, ' monospace'">for (index, element) in collection.indexed {</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">&nbsp; // ...</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">}</span><br></div>
<div>&nbsp;</div>
<div>This should be the preferred idiom when you want both the index and the element.<br></div>
<div>&nbsp;</div>
<div>Note that <span class="font" style="font-family:monospace, ' monospace'">enumerate()</span> does still have valid roles to play:<br></div>
<div>- When you actually do want the element number, not the index.<br></div>
<div>- When you have a <span class="font" style="font-family:monospace, ' monospace'">SequenceType</span>, as it isn't indexed.<br></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>-- Implementation<br></div>
<div>&nbsp;</div>
<div>The feature could be entirely implemented using existing constructs:<br></div>
<div>&nbsp;</div>
<div><span class="font" style="font-family:monospace, ' monospace'">extension CollectionType {</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">&nbsp; var indexed: AnySequence&lt;(Index, Generator.Element)&gt; {</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">&nbsp; &nbsp; return AnySequence(indices.lazy.map { ($0, self[$0]) })</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">&nbsp; }</span><br></div>
<div><span class="font" style="font-family:monospace, ' monospace'">}</span><br></div>
<div>&nbsp;</div>
<div>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></div>
<div>&nbsp;</div>
</div>
<div><img src="https://www.fastmailusercontent.com/proxy/3e1038ac8ff3a8759d181ce58353c8cd6daca3569dfa73d214224cf0eb602127/8647470737a3f2f2777777e266163747d61696c65737562736f6e64756e647e236f6d6f20727f68797f293831363637336536616735346234663130323138393367313035316469366633333330323331603164643731363333673666623035673635323333613135393f283634373437303733373163366236623537323330333033323334333133303335623336343735623337353635663436373632373936343635623566353634373662373736363662366630373536356636633537303735663463313438373635313736373836336637333137313631343167346232333634353432333033343532373237373635643336393434663134363433363033343634643167323731673462323332343433323334333136393733343736313531353734343338373637316534363033356438373137373339333736316538353637353534363634366431673233363731643436313533643164393435343366316430333534363633353237343633353933343530373336353331363235333531343733383333363935326433373733333536643336353732643733336635333636356436643936316434363836313639333536313338373536333730353736323634623233323438373235333534623233363435353464363435343134336431373566373634643334343637353537383539343533323334363837303732663935316631663266373737373033326431363366366431643635393639333633316732343633323331353334366635373033343730373165343636333133353637353134343630373462323336343566373331353437363638343336363731663333323532353933393532353634393430333635333331643164343339343135353437363462333334343462333334343f2f60756e6/open" alt="" width="1" height="1" border="0" 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;"><br></div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div>&nbsp;</div>
<div><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/4c4627058500dd1ff6cd6bf6914c6f51499ed064a6551dfa23148e326b5f9500/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d34575d43723f686b603d22324362777646374e455b4335315e415438374635326541785d4a6258713435396d22324b4230724e4661684d223641665638795f6731423a574576763970353a5768653d22324837357d22324141413a68543545754033553a7863797e4d6d22324d2232497d2236444d2236424a61307432533a485459797a71783461385450386b63697b43795a41366246583943325d463954633a59337768445d69424a67647f674e43343e445a7176587a495733485470743b623d6d22324b473677715538577d2232423a7b69684734794d48467d2232464d414754336641443b683a496346464c6d4536383343703565315234454d2232463b423262543d23344/open"><br></div>
</div>
<div>_______________________________________________<br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div>https://lists.swift.org/mailman/listinfo/swift-evolution<br></div>
</div>
</blockquote></div>
<div>&nbsp;</div>
<div> <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/4b60f421120f8eb4bc9eb2fd94f0f06b898e50df3e3623fd2aff92b190250f67/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e465e624c6961655c646a5374554454615b40313d2236417c4070746f69765b446376433059335134457b4a565257705955357a5d2232474d22324d40775f674b47567a7d2232484d6579635a4a7949493879315857666c6761323848347e675d624862687155437d223648403d41397d4d22324f685d223643525f6938397e68494670596c674c4a5745616369755d2232467350555b6f427860756f603a7947366f44746742534169715441797b67756746635e6351364a547e47593d454a6b6d22324d2236447c49376d22364f6761525366515b61714d23344d23344/open"><br></div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div>&nbsp;</div>
</body>
</html>