## digitalmars.D.learn - Intended behavior of std.range.cycle?

• rcor (21/21) Sep 04 2014 auto c = cycle([1,2,3]);
• monarch_dodra (9/30) Sep 04 2014 Indexing is done with the unsigned size_t. You aren't indexing at
• monarch_dodra (9/10) Sep 04 2014 I re-read your post, and I don't think I actually answered your
• rcor (19/29) Sep 04 2014 To give more detail:
• rcor (3/3) Sep 04 2014 A closer look shows that cycle "repeats the given _forward_ range
• Vlad Levenfeld (9/14) Sep 05 2014 Can you elaborate on what the problem was? I'm curious as I've
• monarch_dodra (17/31) Sep 06 2014 In itself, there is nothing wrong with having a "shallow
"rcor" <murphyslaw480 gmail.com> writes:
```auto c = cycle([1,2,3]);
foreach(i ; iota(-4,4)) {
writeln(c[i]);
}

prints the sequence
1
2
3
1
1   <----- c[0] == c[-1]
2
3

I understand this is what would happen if I were to just use
modulus on an index to access the original array, but should
Cycle really mimic this behavior? I feel like most uses of Cycle
would expect element -1 to be the last element of the original
range, not the first. I could manually apply addition with
modulus to ensure that the index is always positive, but then
there's not much benefit to using cycle anyways -- I might as
well be accessing the original range.
Is this behavior intentional or an oversight?
```
Sep 04 2014
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Thursday, 4 September 2014 at 11:29:30 UTC, rcor wrote:
auto c = cycle([1,2,3]);
foreach(i ; iota(-4,4)) {
writeln(c[i]);
}

prints the sequence
1
2
3
1
1   <----- c[0] == c[-1]
2
3

I understand this is what would happen if I were to just use
modulus on an index to access the original array, but should
Cycle really mimic this behavior? I feel like most uses of
Cycle would expect element -1 to be the last element of the
original range, not the first. I could manually apply addition
with modulus to ensure that the index is always positive, but
then there's not much benefit to using cycle anyways -- I might
as well be accessing the original range.
Is this behavior intentional or an oversight?

Indexing is done with the unsigned size_t. You aren't indexing at
"-1", but rather, size_t.max. size_t.max % 3 probably doesn't
result in "3 - 1" hence what you are observing.

*Should* cycle be negatively index-able? Personally, I don't
think so. And even if it could, it has been proven non-size_t
indexing is not well supported at all. It was de-facto chosen
after the "iota-map fiasco" that all ranges be indexed with
size_t and nothing else...
```
Sep 04 2014
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Thursday, 4 September 2014 at 11:43:28 UTC, monarch_dodra
wrote:
Indexing is done with the unsigned size_t.

question...?

I don't know of any case where you'd want to index negativelly.
That said, I'm sure it could be possible to wrap a cycle into a

There's one issue with what you want to do though: Who is front,
and where does your range start?
```
Sep 04 2014
"rcor" <murphyslaw480 gmail.com> writes:
```On Thursday, 4 September 2014 at 11:58:58 UTC, monarch_dodra
wrote:
On Thursday, 4 September 2014 at 11:43:28 UTC, monarch_dodra
wrote:
Indexing is done with the unsigned size_t.

question...?

I don't know of any case where you'd want to index negativelly.
That said, I'm sure it could be possible to wrap a cycle into a

There's one issue with what you want to do though: Who is
front, and where does your range start?

To give more detail:
I've been working on a strategy game. The player has 'next' and
'previous' buttons they can use to cycle between units they
haven't moved yet. I thought it would be cleaner to use a Cycle
than to have the extra math necessary to wrap the index (its not
that the math is terribly complicated, but it just makes things
messier and less obvious).
In this case, "front" is arbitrarily chosen based on the order in
which the units were loaded. It doesn't really matter who is
front as long as each press of 'next' or 'previous' jumps to a
new unit.
The "negative" index occurs when the player has unit 0 selected
and presses 'previous'. Instead of jumping to the previous unit,
the cursor sticks on the same unit (at least in the situation
where size_t.max % numUnits == 0).

It's not a huge deal to work around it in my own code, but I
figured I should point it out in case this was unintentional.
```
Sep 04 2014
"rcor" <murphyslaw480 gmail.com> writes:
```A closer look shows that cycle "repeats the given _forward_ range
indefinitely", so I guess the current behavior is at least
consistent with the docs.
```
Sep 04 2014
```On Thursday, 4 September 2014 at 11:43:28 UTC, monarch_dodra
wrote:
*Should* cycle be negatively index-able? Personally, I don't
think so. And even if it could, it has been proven non-size_t
indexing is not well supported at all. It was de-facto chosen
after the "iota-map fiasco" that all ranges be indexed with
size_t and nothing else...

Can you elaborate on what the problem was? I'm curious as I've
recently implemented a DSP module that uses ranges with
floating-point slicing and, other than having to define a second
kind of length (I call it "measure" so I can still have a
discrete length when I need it), it seems to work well enough so
far. It'd be bad if there were some unseen fiasco waiting for
me...
```
Sep 05 2014
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Friday, 5 September 2014 at 10:41:22 UTC, Vlad Levenfeld wrote:
On Thursday, 4 September 2014 at 11:43:28 UTC, monarch_dodra
wrote:
*Should* cycle be negatively index-able? Personally, I don't
think so. And even if it could, it has been proven non-size_t
indexing is not well supported at all. It was de-facto chosen
after the "iota-map fiasco" that all ranges be indexed with
size_t and nothing else...

Can you elaborate on what the problem was? I'm curious as I've
recently implemented a DSP module that uses ranges with
floating-point slicing and, other than having to define a
second kind of length (I call it "measure" so I can still have
a discrete length when I need it), it seems to work well enough
so far. It'd be bad if there were some unseen fiasco waiting
for me...

In itself, there is nothing wrong with having a "shallow
container" that can be indexed from -inf to +inf. The "issues"
might appear if you try to tag on the "range" interface on it.

In particular, who is "front"? If I do a "foreach" over the
sequence, then will it miss half the elements? What does it mean
to slice from -5 to +5 ? Which element becomes the "new" 0?

As for floating point indexing, it's the same thing. The indexing
itself is fine, there's no problem there. But if you popFront,
how many elements are you actually skipping over. What would it
mean if I were to "take(4.5)" elements?

*Overall*, it should be fine, but if you are creative, you could
hurt yourself. I don't know your exact use case though.

So my conclusion is mostly that as long as you only index, you
should be fine. Mix in range adaptors, and things *could* become
less stable. *could*. But you should still be mostly safe. Again,
depends on use case.
```
Sep 06 2014