[swift-evolution] Feature proposal: Range operator with step
Dave Abrahams
dabrahams at apple.com
Wed Apr 6 13:16:07 CDT 2016
on Wed Apr 06 2016, Xiaodi Wu <xiaodi.wu-AT-gmail.com> wrote:
> I think a lightbulb just went on for me:
>
> You're talking about expressing something in the vein of `(0..<200).striding(by:
> -2)`, which has I'm sure many use cases, and which isn't straightforward to
> express with the current free function--I hadn't considered that.
>
> Meanwhile, I was trying to talk about something like `stride(from: 200, to: 0,
> by: -2)`, which is easily expressed today but isn't straightforward at all to
> preserve with only ranges. Clearly, given that this is what's on offer
> currently, someone who designed the language thinks (or thought) it's of some
> use.
That someone was me, and I explained that it wasn't an extremely
deeply-considered decision.
> In the absence of information as to which is more in demand, couldn't
> we have both?
That's not how we make decisions about what should be in the language or
standard library. We need to make choices based on (at least educated
guesses about) what people need, or we'll end up with a sprawling mess.
> If it must be a method on a range,
It's not that it must be, but having such a method tends to reduce API
surface area. We prefer methods to free functions.
> then I would advocate for having what seems to be an utterly
> reasonable set of options for striding backwards:
>
> ```
> (0...200).striding(by: -2) // [a, b]
> (0..<200).striding(by: -2) // [a, b)
> (0<..200).striding(by: -2) // (a, b]
> ```
And I'm trying to say that without a more compelling reason to introduce
`<..`, I don't want to do it. I'd like to know that `<..` is useful
outside the domain of striding, for example. Use-cases, anyone?
Reasons we might not need it: the cases where it's important are much
more likely to be notionally continuous domains (e.g. floats), since you
can always write
((0+1)...200).striding(by: -2)
and if you need the floating version there's always
(0.0...200.0).striding(by: -2).lazy.filter { $0 != 0.0 }
which probably optimizes down to the same code.
One question that I *do* think we should answer, is whether the elements
of
(0..<199).striding(by: -2)
are even or odd.
> On Wed, Apr 6, 2016 at 12:10 PM Dave Abrahams via swift-evolution
> <swift-evolution at swift.org> wrote:
>
> on Wed Apr 06 2016, Brent Royal-Gordon <brent-AT-architechies.com> wrote:
>
> >> For example, there are all kinds of other ways to slice this:
> >>
> >> stride(over: 0..<200, by: -2)
> >
> > This seems like a particularly good solution. The way I understand it
> > at least, it would allow ranges to always be ordered, with the only
> > difference being whether it went start-to-end or end-to-start,
> > determined by the stride's sign.
>
> This is no different in principle from
>
> (0..<200).striding(by: -2)
>
> Again, I wasn't trying to suggest any of the solutions listed there.
> The point I was making was that we don't have enough information to
> design more than
>
> (0..<200).striding(by: -2)
>
> > It would also avoid the need for additional range operators. The main
> > reason you would need `>..` is so you could say
> > `array.endIndex>..array.startIndex`, but by using the sign to decide
> > which direction to stride over the range, you instead stride over
> > `array.startIndex..<array.endIndex`, which is exactly what we already
> > have.
> >
> > Unfortunately, moving away from `stride(from:to/through:by:)` would
> > kind of mess up an idea I've been developing for providing an
> > "induction sequence" to replace the more complicated C-style for use
> > cases, but I suppose that's the way it goes...
> >
> > (Link to that:
> https://gist.github.com/brentdax/b24dd89a770d9fe376984498d3185187)
>
> --
> Dave
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
--
Dave
More information about the swift-evolution
mailing list