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:
striding.md · GitHub 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
<striding.md · GitHub;
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)
<striding.md · GitHub;
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).
<striding.md · GitHub
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.
<striding.md · GitHub
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.
<striding.md · GitHub
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.
<striding.md · GitHub;
Acknowlegements
Thanks, Dave Abrahams, Matthew Judge
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution