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