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

Dave Abrahams dabrahams at apple.com
Sun Apr 10 12:06:54 CDT 2016


on Sun Apr 10 2016, Michel Fortin <swift-evolution at swift.org> wrote:

> Le 10 avr. 2016 à 6:17, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> a écrit :
>
>> Remember, conditional branches are relatively slow, and we want to
> avoid them where we can. If this is, for instance, the test of a loop,
> the extra branch is not a good thing.
>
> Perhaps it's a bit extreme, but my idea for stride is that it should
> only have one branch in the loop condition and absolutely no other
> branch. 

I agree that would be ideal.  When the stride is statically known, I am
confident that the optimizer can eliminate the branch.  When the stride
is not statically known, presumably you need the branch anyway, though
one might have to hope for the optimizer to copy and split the loop
(i.e. create two specializations based on sign).

> The primitive stride could be defined like this:
>
> 	stride(from: 0, compare: <, to: 10, by: 2)

Now you're adding a function call in lieu of a branch.  We could easily
build stride so it stores a comparison function based on the sign of the
stride, if we thought this would be better.  Would it?

> and on top you could add some convenience functions for the <, >, <=, and >= cases:
>
> 	stride(from: 0, to: 10, by: 2) // stride(from: 0, compare: <, to: 10, by: 2)
> 	stride(from: 10, downTo: 0, by: -2) // stride(from: 10, compare: >, to: 0, by -2)
>
> 	stride(from: 0, through: 10, by: 2) // stride(from: 10, compare: <=, to: 10, by 2)
> 	stride(from: 10, downThrough: 0, by: -2) // stride(from: 10, compare: >=, to: 0, by -2)
>
> None of these should try to prevent you from making an infinite
> sequence, so no trap for `by: 0` or one that moves the value in the
> wrong direction. And certainly no extra loop branch based on the sign
> of the stride (that's the most important part).
>
> Based on that, you could add some convenience for ranges:
>
> 	(0 ..< 10).striding(by: 2) // shortcut for: stride(from: 0, to: 10, by 2)
> 	(0 ..< 10).stridingDown(by: -2) // shortcut for: stride(from: 10, to: 0, by -2)
>
> I guess in this case it'd be fine to add a precondition to check that
> `by` is not in the reverse direction so we can preserve the semantics
> of iterating over a collection. But because of this precondition and
> the other one in Range, I would actually prefer the non-range forms if
> I was using a `stride` in a nested loop.

-- 
Dave



More information about the swift-evolution mailing list