I like <font size="2"><span style="background-color:rgba(255,255,255,0)">(10 … 0).stride(2) including the change that (10 … 0) would be an empty sequence and not an error.</span></font><br><br>On Friday, 4 March 2016, Dave Abrahams via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
on Tue Mar 01 2016, Haravikk &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a>&gt; wrote:<br>
<br>
&gt; I still wonder if a better solution might involve the same syntax as ranges currently benefit from, i.e:<br>
&gt;<br>
&gt;       0 ..&lt; 10 // [0, 10) with an increment of 1<br>
&gt;       (0 … 10).stride(2) // [0, 10] with an increment of 2<br>
&gt;<br>
&gt; The most important change is that the default type for this should be able to handle higher starting indices, e.g:<br>
&gt;<br>
&gt;       (10 … 0).stride(2) // [10, 0] with a decrement of 2<br>
<br>
I like this approach a lot.  We have lots of different ways to express<br>
variations on ranges and intervals today that don&#39;t actually involve the<br>
range operators (including prefixTo, suffixFrom, stride).  IMO they<br>
should.<br>
<br>
The one problem I anticipate is that negative strides won&#39;t work well,<br>
because forming (a...b) will have a precondition that a &lt;= b.<br>
<br>
&gt; Basically I don’t like the stride global function in the first place =)<br>
&gt;<br>
&gt; The benefit of the Range syntax is that it’s clear whether the end<br>
&gt; point is inclusive or exclusive, and it’s nice and succinct. The<br>
&gt; problem right now is just that ranges have a limit on the direction<br>
&gt; they can be traversed in for things like accessing slices of<br>
&gt; collections, in which case we’ll need to make sure that these still<br>
&gt; retain the same limitation.<br>
&gt;<br>
&gt;&gt; On 1 Mar 2016, at 08:54, Xiaodi Wu via swift-evolution &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; It&#39;s so nice to see such care devoted to clarifying these existing<br>
&gt;&gt; names. I agree with the premise that stride(to:by:) and<br>
&gt;&gt; stride(through:by:) are poorly named, but I&#39;d like to make two<br>
&gt;&gt; critiques of this proposal--<br>
&gt;&gt;<br>
&gt;&gt; Critique 1:<br>
&gt;&gt;<br>
&gt;&gt; The basic distinction between the two current stride styles is that<br>
&gt;&gt; one is inclusive and the other is exclusive of the end value. I agree<br>
&gt;&gt; with you that &quot;to&quot; doesn&#39;t imply an exclusive end value, but &quot;towards&quot;<br>
&gt;&gt; doesn&#39;t imply that the parameter is any sort of end value at<br>
&gt;&gt; all--rather, it implies just a direction (or as you quote from the<br>
&gt;&gt; NOAD, getting close or closer).<br>
&gt;&gt;<br>
&gt;&gt; Two implications:<br>
&gt;&gt;<br>
&gt;&gt; First, if I stride from 10 towards 0 by 1, by the plain English<br>
&gt;&gt; meaning of the word &quot;towards&quot;, I would expect to obtain 10, 9, 8, 7,<br>
&gt;&gt; 6, etc. If we simply rename stride(to:by:) to stride(towards:by:), I<br>
&gt;&gt; would not get that result. By contrast, it makes sense from the<br>
&gt;&gt; current name that stride(to:by:) attempts to increment using the `by`<br>
&gt;&gt; parameter without considering whether the end value is greater than or<br>
&gt;&gt; less than the start value; if you can&#39;t get from here &quot;to&quot; there by<br>
&gt;&gt; such increments, too bad!<br>
&gt;&gt;<br>
&gt;&gt; Second, if I stride from 0 towards 10 by 1 (in the English language,<br>
&gt;&gt; not in Swift), I may or may not stop short of 10 itself. That is,<br>
&gt;&gt; whether &quot;towards&quot; is inclusive or exclusive of the end value can&#39;t be<br>
&gt;&gt; inferred from the meaning of the word; after all, if I&#39;m making<br>
&gt;&gt; strides towards a goal, I do intend to reach it, or at least that&#39;s<br>
&gt;&gt; what I tell people when they ask how my PhD is going...<br>
&gt;&gt;<br>
&gt;&gt; Generalizing from the word &quot;towards&quot;, I don&#39;t know that any two<br>
&gt;&gt; prepositions in the English language can be used unambiguously to<br>
&gt;&gt; convey the distinction between inclusive and exclusive end values.<br>
&gt;&gt; Although, on some additional thought--if I had to suggest a<br>
&gt;&gt; preposition, perhaps &quot;until&quot; or &quot;till&quot; would be more apt than<br>
&gt;&gt; &quot;towards&quot;.<br>
&gt;&gt;<br>
&gt;&gt; The saving grace of &quot;to&quot; and &quot;through&quot; in the current situation is<br>
&gt;&gt; that the latter seems intuitively to go further than the former, and<br>
&gt;&gt; if one deduces by analogy with the range operators that one of these<br>
&gt;&gt; must exclude the end value and the other include it, then the two<br>
&gt;&gt; names must mean what they do today. With three stride styles and three<br>
&gt;&gt; prepositions, but only two range operators, this intuition is broken,<br>
&gt;&gt; while the prepositions may not get much clearer (though I must admit<br>
&gt;&gt; that your proposed use of &quot;to&quot; is an improvement).<br>
&gt;&gt;<br>
&gt;&gt; Critique 2:<br>
&gt;&gt;<br>
&gt;&gt; The original motivation behind your twin proposals was the epsilon<br>
&gt;&gt; adjustment necessary for floating point end values. Your other<br>
&gt;&gt; proposal fixes an issue with accumulated errors but doesn&#39;t solve the<br>
&gt;&gt; need for an epsilon adjustment. Here, you propose adding a third<br>
&gt;&gt; stride style to solve that problem, along the way shuffling the naming<br>
&gt;&gt; of the existing stride styles. Since you haven&#39;t presented other use<br>
&gt;&gt; cases for that third stride style here, and you haven&#39;t listed<br>
&gt;&gt; alternatives considered for solving the original motivating problem<br>
&gt;&gt; (i.e. epsilon adjustment), let me propose one alternative:<br>
&gt;&gt;<br>
&gt;&gt; Keep the naming of stride styles as-is (inapt as they may be), and for<br>
&gt;&gt; floating point end values make stride(through: aNumber, by: something)<br>
&gt;&gt; equivalent to stride(to: theNextLargestRepresentableNumber, by:<br>
&gt;&gt; somethingPositive) or stride(to: theNextSmallestRepresentableNumber,<br>
&gt;&gt; by: somethingNegative). Would that solve your original issue<br>
&gt;&gt; adequately?<br>
&gt;&gt;<br>
&gt;&gt; Alternatively, if there are lots of examples that can be envisioned<br>
&gt;&gt; for this third stride style, would the same examples suggest perhaps<br>
&gt;&gt; that `..&gt;` might be a useful third range operator?<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Mon, Feb 29, 2016 at 7:14 PM, Erica Sadun via swift-evolution<br>
&gt;&gt; &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On Feb 29, 2016, at 5:03 PM, Joe Groff &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;jgroff@apple.com&#39;)">jgroff@apple.com</a>&gt; wrote:<br>
&gt;&gt;&gt; I agree, splitting into two proposals is a good idea.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -Joe<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Conventionalizing stride semantics<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Proposal: SE-00NN<br>
&gt;&gt;&gt; Author(s): Erica Sadun<br>
&gt;&gt;&gt; Status: TBD<br>
&gt;&gt;&gt; Review manager: TBD<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Swift offers two stride functions, stride(to:, by:) and stride(through:,<br>
&gt;&gt;&gt; by:). This proposal introduces a third style and renames the existing to and<br>
&gt;&gt;&gt; through styles.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; This proposal was discussed on-list in the &quot;[Discussion] stride behavior and<br>
&gt;&gt;&gt; a little bit of a call-back to digital numbers&quot;thread.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Motivation<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Strideable&#39;s function names do not semantically match the progressions they<br>
&gt;&gt;&gt; generate. Values produced by throughdo not pass through an end point; they<br>
&gt;&gt;&gt; stop at or before that fence. For example, 1.stride(through: 10, by: 8)<br>
&gt;&gt;&gt; returns the progress (1, 9), not (1, 9, 17). Similarly, its to function<br>
&gt;&gt;&gt; values reaches its end point. 1.stride(to:4, by:1) returns 1, 2, and 3. It<br>
&gt;&gt;&gt; never makes it to 4:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The current Swift definition of to returns values in [start, end) and will<br>
&gt;&gt;&gt; never reach end. In other words, you will never get to end.<br>
&gt;&gt;&gt; The current Swift definition of through returns values in [start, end]. It<br>
&gt;&gt;&gt; may never reach end and certainly never goes through that value.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Some definitions with the help of the New Oxford American Dictionary<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Moving to a value expresses &quot;a point reached at the end of a range&quot;.<br>
&gt;&gt;&gt; To pass through a value, you should move beyond &quot;the position or location of<br>
&gt;&gt;&gt; something beyond or at the far end of (an opening or an obstacle)&quot;.<br>
&gt;&gt;&gt; To move towards a value is to get &quot;close or closer&quot; or &quot;getting closer to<br>
&gt;&gt;&gt; achieving (a goal)&quot;.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Current Art<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; A Strideable to sequence returns the sequence of values (self, self +<br>
&gt;&gt;&gt; stride, self + stride + stride, ... last) where last is the last value in<br>
&gt;&gt;&gt; the progression that is less than end.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; A Strideable through sequence currently returns the sequence of values<br>
&gt;&gt;&gt; (self, self + stride, self + tride + stride, ... last) where last is the<br>
&gt;&gt;&gt; last value in the progression less than or equal to end. There is no<br>
&gt;&gt;&gt; guarantee that end is an element of the sequence.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The name of the calling function through suggests the progression will pass<br>
&gt;&gt;&gt; through the end point before stopping. It does not. The name to suggests a<br>
&gt;&gt;&gt; progression will attempt to arrive at an end point. It does not.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Detail Design<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; When striding to or through a number, the behavior does not match the<br>
&gt;&gt;&gt; meaning of the word. Swift should provide three stride styles not two.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Style 1: [start, end) by interval<br>
&gt;&gt;&gt; This style is currently called to. I propose to rename it towards as each<br>
&gt;&gt;&gt; value works towards end. The final value in the progression is less than end<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Style 2: [start, end] by interval<br>
&gt;&gt;&gt; This style is currently called through. I propose to rename it to. The<br>
&gt;&gt;&gt; progression concludes with a value that is less than or equal to end. Swift<br>
&gt;&gt;&gt; provides no guarantee that end is an element of the sequence.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Style 3: [start, &gt;=end] by interval<br>
&gt;&gt;&gt; I propose to introduce a new style called through. The final value is<br>
&gt;&gt;&gt; guaranteed to pass through end, either by finishing on end or past end. The<br>
&gt;&gt;&gt; final value is strictly less than end + interval.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; A Style 3 implementation works as follows:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; /// A `Strideable through` sequence currently returns the sequence of values<br>
&gt;&gt;&gt; /// (`self`, `self + stride`, `self + stride + stride`, ... *last*) where<br>
&gt;&gt;&gt; *last*<br>
&gt;&gt;&gt; /// is the first value in the progression **greater than or equal to**<br>
&gt;&gt;&gt; `end`.<br>
&gt;&gt;&gt; /// There is no guarantee that `end` is an element of the sequence.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;    /// Advance to the next element and return it, or `nil` if no next<br>
&gt;&gt;&gt;    /// element exists.<br>
&gt;&gt;&gt;    public mutating func next() -&gt; Element? {<br>
&gt;&gt;&gt;        if done {<br>
&gt;&gt;&gt;            return nil<br>
&gt;&gt;&gt;        }<br>
&gt;&gt;&gt;        if stride &gt; 0 ? current &gt;= end : current &lt;= end {<br>
&gt;&gt;&gt;            done = true<br>
&gt;&gt;&gt;            return current<br>
&gt;&gt;&gt;        }<br>
&gt;&gt;&gt;        let result = current<br>
&gt;&gt;&gt;        current = current.advancedBy(stride)<br>
&gt;&gt;&gt;        return result<br>
&gt;&gt;&gt;    }<br>
&gt;&gt;&gt; }<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; This solution is minimally disruptive to developers, respectful to existing<br>
&gt;&gt;&gt; code bases, and introduces a more complete semantic set of progressions that<br>
&gt;&gt;&gt; better matches progression names to developer expectations. (For example,<br>
&gt;&gt;&gt; &quot;this argument says it goes through a value but it never even reaches that<br>
&gt;&gt;&gt; value&quot;.)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Upon adopting this change, out-of-sync strides now pass through end values:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // Unit stride<br>
&gt;&gt;&gt; print(Array(1.stride(through: 10, by: 1)))<br>
&gt;&gt;&gt; // prints [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], no change<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // Old out-of-sync stride<br>
&gt;&gt;&gt; print(Array(1.stride(through: 10, by: 8)))<br>
&gt;&gt;&gt; // prints [1, 9]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // New out-of-sync stride<br>
&gt;&gt;&gt; print(Array(1.stride(through: 10, by: 8)))<br>
&gt;&gt;&gt; // prints[1, 9, 17]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; There are no functional changes existing stride implementations. Only their<br>
&gt;&gt;&gt; names change.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; print(Array(1.stride(towards: 10, by: 8))) // was `to`<br>
&gt;&gt;&gt; // prints [1, 9]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; print(Array(1.stride(to: 10, by: 8))) // was `through`<br>
&gt;&gt;&gt; // prints [1, 9]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Although floating point arithmetic presents a separate and orthogonal<br>
&gt;&gt;&gt; challenge, its behavior changes if this proposal is implemented under the<br>
&gt;&gt;&gt; current generic system. For example, through now includes a value at (or at<br>
&gt;&gt;&gt; least close to) 2.0 instead of stopping at 1.9 due to accumulated floating<br>
&gt;&gt;&gt; point errors.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // Old<br>
&gt;&gt;&gt; print(Array(1.0.stride(through: 2.0, by: 0.1)))<br>
&gt;&gt;&gt; // prints [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // New<br>
&gt;&gt;&gt; print(Array(1.0.stride(through: 2.0, by: 0.1)))<br>
&gt;&gt;&gt; // prints [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // Old, does not pass through 1.9<br>
&gt;&gt;&gt; print(Array(1.0.stride(through: 1.9, by: 0.25)))<br>
&gt;&gt;&gt; // prints [1.0, 1.25, 1.5, 1.75]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; // New, passes through 1.9<br>
&gt;&gt;&gt; print(Array(1.0.stride(through: 1.9, by: 0.25)))<br>
&gt;&gt;&gt; // prints [1.0, 1.25, 1.5, 1.75, 2.0]<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Impact on Existing Code<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Renaming two stride functions and adding a third does not change or break<br>
&gt;&gt;&gt; existing code. The Swift 3 migrator can easily update the names for the two<br>
&gt;&gt;&gt; existing styles. That said, the migrator will not find in-place workarounds<br>
&gt;&gt;&gt; like a through: 2.01 epsilon adjustment to correct for floating-point<br>
&gt;&gt;&gt; fences. By adding FIXME: notes wherever through: is found and renamed to<br>
&gt;&gt;&gt; to:, the migrator could warn against continued use without a full inspection<br>
&gt;&gt;&gt; and could offer links to information about the semantic changes.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Alternatives Considered<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The only alternative at this time is &quot;no change&quot; to existing semantics.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; _______________________________________________<br>
&gt;&gt;&gt; swift-evolution mailing list<br>
&gt;&gt;&gt; <a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a><br>
&gt;&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;&gt;&gt;<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; swift-evolution mailing list<br>
&gt;&gt; <a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a><br>
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br>
--<br>
-Dave<br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;swift-evolution@swift.org&#39;)">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote><br><br>-- <br>-- Howard.<br>