# [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

Xiaodi Wu xiaodi.wu at gmail.com
Sat Apr 9 04:50:04 CDT 2016

```I agree with 90% of your comment.

But, ranges are useful for more than just stride, and so I would say it
doesn't make sense to have an intrinsic direction for Range, which
pointedly has lowerBound and upperBound but not start and end. For sample,
there shouldn't be (0...9).contains(1) and (9...0).contains(1).

It's the *traversal* of the range by a stride that has a direction, and
thus the direction should be specified for a particular stride.

Similarly, the rationale for completing the range operators is for the uses
of range that include but are not limited to just stride. If it were just
for stride, then four range operators is three too many.
On Sat, Apr 9, 2016 at 10:33 AM Haravikk <swift-evolution at haravikk.me>
wrote:

> While I’m in favour of the basic idea I think the operator selection is
> too complex, and I’m not sure about the need for negative strides. Really
> all I want are the following:
>
> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>
> Everything else should be coverable either by flipping the order, or using
> .reverse(). The main advantage is that there’s only one new operator to
> clarify the 6 ..> 0 case, though you could always just reuse the existing
> operator if you just interpret it as “x from 6 to, but not including, 0"
>
> I dunno, I just don’t think that introducing tons of new operators is
> going to simplify things, and could lead to way more mistakes in practice;
> the only mistake above would be putting the indices in the wrong order and
> accidentally reversing the result.
>
> Also, I’m against negative strides; while they could be useful for
> convenience (avoid the need for .reverse or flipping values) I’m just not
> sure that it makes sense. To me a stride is a distance, thus absolute, what
> matters is the direction of the range. Naturally we’d need ranges with a
> direction, but with collections requiring it to be in a particular order
> (or ignoring it and flipping where necessary).
>
> On 8 Apr 2016, at 19:37, Erica Sadun via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Draft here: https://gist.github.com/erica/a51a981ee0352235204692affa959307  Feedback
> solicited, both positive and negative.
> We've also got a related proposal about expanding ranges, which you can
> look at here (
> https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9)
>  but we want to float this one first.
>
> Thanks, -- E
>
>
>
>
>    - Proposal: SE-XXXX
>    <https://gist.github.com/erica/a51a981ee0352235204692affa959307/edit>
>    - Author(s): Xiaodi Wu <https://github.com/xwu>, Pyry Jahkola
>    <http://github.com/pyrtsa>, Nate Cook <http://github.com/natecook1000>
>    - Status: TBD
>    - Review manager: TBD
>
>
> <https://gist.github.com/erica/a51a981ee0352235204692affa959307#introduction>
> Introduction
>
> We propose to introduce a striding(by:) method on the revised 3.0 Range
>  type.
>
> This proposal was discussed on the Swift Evolution list in the Feature
> proposal: Range operator with step
> <https://gist.github.com/erica/a51a981ee0352235204692affa959307#motivation>
> Motivation
>
> Updating Range for Swift 3 offers a window of opportunity to
> simultaneously improve strides.
>
>    -
>
>    Under current Swift 3 plans, n.stride(to:/through:, by:) will be
>    replaced with a standalone stride(from:, to:/through:, by:) function.
>    We propose to replace this change with a method on ranges. Using a method
>    reduces overall API surface area compared to free functions.
>    -
>
>    In its current incarnation, the standalone stride function uses
>    confusing semantics. The current to implementation returns values in
>    *[start, end)* and will never reach or get *to* end. The current
>    through implementation returns values in *[start, end]*. It may never
>    reach end and certainly never goes *through* that value. Our proposed
>    method introduces simple, expected semantics that can be extended to both
>    countable and continuous ranges, and to open and closed intervals (both
>    half-open and fully-open).
>
>
> <https://gist.github.com/erica/a51a981ee0352235204692affa959307#detail-design>Detail
> Design
>
> The striding(by:) method is called on ranges. When used with a positive
> step size, the count starts from the lower bound. With a negative step
> size, the count starts from the upper bound. These bounds apply regardless
> of whether they are inclusive or exclusive.
>
> The following examples should cover all corner cases and include possible
> cases should Swift 3 introduce a full complement of open and closed ranges.
> The syntax for non-canonical range types is not fixed and can be discussed
> under separate cover.
>
> (0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 <.. 9).striding(by: 2) ==    [2, 4, 6, 8]
> (0 <.< 9).striding(by: 2) ==    [2, 4, 6, 8]
>
> (0 ... 9).striding(by: 3) == [0, 3, 6, 9]
> (0 ..< 9).striding(by: 3) == [0, 3, 6]
> (0 <.. 9).striding(by: 3) ==    [3, 6, 9]
> (0 <.< 9).striding(by: 3) ==    [3, 6]
>
> (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
> (0 ..< 9).striding(by: -2) ==    [7, 5, 3, 1]
> (0 <.. 9).striding(by: -2) == [9, 7, 5, 3, 1]
> (0 <.< 9).striding(by: -2) ==    [7, 5, 3, 1]
>
> (0 ... 9).striding(by: -3) == [9, 6, 3, 0]
> (0 ..< 9).striding(by: -3) ==    [6, 3, 0]
> (0 <.. 9).striding(by: -3) == [9, 6, 3]
> (0 <.< 9).striding(by: -3) ==    [6, 3]
>
> To reverse a stride, call reverse() on the results:
>
> (0 ... 9).striding(by: 2).reverse() == [8, 6, 4, 2, 0]
>
> We note that striding by 0 should be always be a precondition failure.
>
> <https://gist.github.com/erica/a51a981ee0352235204692affa959307#alternatives-considered>Alternatives
> Considered
>
> During the on-list discussion, we considered various scenarios that took
> closed/inclusive bounds into account or excluded open bounds for starting
> values. For example, we might have prohibited scenarios where multiple
> interpretations of an intended behavior might exist: is (0 ..<
> 9).striding(by: -2) a precondition failure? We settled on the simplest,
> most straight-forward implementation involving the fewest compiler warnings
> and the lowest likelihood of precondition failures. We subscribe to the
> "Dave Abrahams Philosophy": excessive special casing and warning scenarios
>
> <https://gist.github.com/erica/a51a981ee0352235204692affa959307#future-directions>Future
> Directions
>
> We intend to follow up with an expanded operator vocabulary that includes
> fully open ranges (<.<), fully closed ranges (...) and both half open
> ranges (<.., ..<). These will support the full vocabulary laid out in the
> Detail Design section.
>
> Upon adoption, the Swift community may consider expanding this approach to
> collection indices, for example:
>
> let a = [8, 6, 7, 5, 3, 0, 9]
> for e in a.striding(by: 3) {
>     print(e) // 8, then 5, then 9
> }
>
> Striding offers a fundamental operation over collections. The consistent
> approach introduced in this proposal
> <http://article.gmane.org/gmane.comp.lang.swift.evolution/13936> helps
> support the extension of stride semantics to collections.
>
> <https://gist.github.com/erica/a51a981ee0352235204692affa959307#acknowlegements>
> Acknowlegements
> Thanks, Dave Abrahams, Matthew Judge
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160409/07340179/attachment.html>
```