<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>I like this idea. The problem is that it would require that we have an Index.NonNegativeDistance as argument to really make it statically safe. And we would have to have methods producing these, probably as optional return values.</div><div>Otherwise we won't have achieved statically safety but effectively just better documentation about the capabilities of the respective collection.</div><div><br></div><div>-Thorsten </div><div><br></div><div><br></div><div>Am 31.05.2016 um 14:46 schrieb Haravikk 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">So for Swift 3 we’re going to have the great new indexing model that performs index manipulation through the collection to which an index belongs.<div class=""><br class=""></div><div class="">However, it retains one of the things I didn’t like about the old model, which is that the distinction between forward/backward only types is a bit fuzzy, since the single advancedBy() method, now the index(:offsetBy:) method, was used for both forward and backward movement, which seems contradictory compared to the forward/backward only single-step methods.</div><div class=""><br class=""></div><div class="">Anyway, I’m wondering what people’s thoughts would be on tweaking the formula slightly such that there are methods that only work in a particular direction, i.e- we’d have three main variations of the methods like so:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">public</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> index(</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> index:</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">, advancedBy:</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Distance</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">) -> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> { … } </span>// Available on forward and bidirectional collections</div><div style="margin: 0px; font-size: 11px; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">public</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> index(</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> index:</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">, reversedBy:</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Distance</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">) -> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> { … } </span>// Available on reverse and bidirectional collections</div><div style="margin: 0px; font-size: 11px; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">public</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> index(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span> index:<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span>, offsetBy:<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Distance</span>) -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Index</span> { … } <span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// Available only on bidirectional collections</span></div></div><div class=""><br class=""></div><div class="">(note, the naming isn’t definite, as reversed may not be clear enough, it’s just an example for now)</div><div class=""><br class=""></div><div class="">There are three reasons I’d prefer this:</div><div class=""><br class=""></div><div class="">The first is that I can pass the same distance into either of the first two methods, and any negation etc. is handled internally. In essence I shouldn’t have to handle negative distances at all when working with the first two methods. So if I’m working with a step size of 5, I can just pass that into the appropriate method, I never have to do anything with it the value itself.</div><div class=""><br class=""></div><div class="">The second benefit is that there should be no uncertainty about the capabilities of the type you’re using; if it doesn’t have the index(:reversedBy:) method then you can’t go backwards, same as index(before:) and index(after:).</div><div class=""><br class=""></div><div class="">The third and main benefit is that the methods are just more explicit about what they do, and what direction you can go in; passing negatives into either of the first two would produce errors outright, allowing you to pick on mistakes in these cases.</div><div class=""><br class=""></div><div class="">The other main thing is that offsetBy doesn’t indicate whether a type supports forward-only offsets, you have to read the documentation to determine this either in the method itself or the type, whereas the presence or absence of the first two variants are pretty clear.</div><div class=""><br class=""></div><div class="">Currently the offsetBy, and the previous advancedBy(), methods require forward-only types to produce fatal errors if handed a negative distance, and vice versa for backward-only types, which can only produce errors at runtime, whereas the presence or absence of the first two methods can be handled during development. You could still pass a negative value and end up with a runtime error instead of course, but for the types of common uses they’re intended for you should be unlikely to produce one.</div><div class=""><br class=""></div><div class="">The offsetBy form would still exist for bidirectional collections, but would only really be used when you need to do more complex index/distance manipulation outside of the type where a calculation might produce either positive or negative values (e.g- if you're calculating the distance and don’t know where two indices are in relation to each other), the rest of the time you should try to use the more specific, single-direction forms as they clarify your intent and can help to catch mistakes if you’ve incorrectly generated a distance for example.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Just curious what other people’s thoughts are about this?</div><div class=""><br class=""></div><div class="">I intended to mention this a lot sooner (to change advancedBy), but then I find out about the new indexing model so thought I’d wait until afterwards, then completely forgot =)</div></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></body></html>