IMO, 9...0 is a non-starter. Especially with Range taking on the role of Interval, it's critical that they have no direction. Suppose you have two ranges, 0...9 and 9...0. Is 0...9 == 9...0? IMO, two countable ranges r0 and r1 are equal if, for value in r0, r1.contains(value) == true, and vice versa. (Sorry for the pseudocode; I'm typing on a phone.) However, if Range has intrinsic direction, either equality ignores direction (ludicrous) or 0...9 != 9...0 (unacceptable).
Since we have `reverse()`, all ambiguity could be resolved by prohibiting negative stride sizes altogether, I suppose. So, (0...9).striding(by: 2).reverse() could be the one Swifty way to stride backwards. Is that objectionable to people? On Sat, Apr 9, 2016 at 11:58 PM Haravikk <swift-evolut...@haravikk.me> wrote: > On 9 Apr 2016, at 10:50, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > 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). > > > While I can appreciate that, I wonder if it’s really that important that > 0…9 and 9…0 are identical? As long as we can be clear on which direction of > range we want to generate (so probably still need two new operators), can > tell what the direction is, and can convert between them if we need to for > some reason (reverse should be fine for that?), then I think we’re okay. > > i.e- 9 … 0 would still cause an error at compile or run-time, we’d have > some other operator for doing that, not sure what, plus 9 ..> 0, with both > explicitly creating ranges in the reverse direction to avoid mistakes with > the order or for computed indices. When it comes down to it the current > Range has an implicitly forward direction, so I don’t see the problem with > having the same in reverse personally. > > > I dunno, at the very least we might want to consider overloading the > striding method as .striding(forwardBy:) and .striding(backwardBy:) or > something similar, each taking a positive value of some kind to help avoid > mistakes in cases where the stride size is computed rather than constant, > this would make it more explicit at least. > > On Sat, Apr 9, 2016 at 10:33 AM Haravikk <swift-evolut...@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@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> >> , Erica Sadun <http://github.com/erica> >> - 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 >> <http://search.gmane.org/search.php?group=gmane.comp.lang.swift.evolution&query=Feature+proposal%3A+Range+operator+with+step> >> thread. >> (Direct link >> <http://thread.gmane.org/gmane.comp.lang.swift.evolution/12801/focus=13051> >> to >> original thread) >> >> <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 >> more likely indicates bad language design than bad user comprehension. >> >> <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@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution