`IntProgression` is quite inconvenient to work wit...
# stdlib
c
IntProgression
is quite inconvenient to work with… To model progressions that can be open-ended, I use
0
as a minimum and
Int.MAX_VALUE
as a maximum. However, when querying an actual list, I don't want to iterate over all the values larger than the array items. For example:
Copy code
val range = 5..Int.MAX_VALUE
val list = listOf(...)

for (index in range) {
    if (index in list.indices) {
        ...
    }
}
is very wasteful, because almost all values from
range
won't be in
list.indices
. I expected to be able to write:
Copy code
for (index in range.coerceIn(list.indices)) {
    ...
}
but this function doesn't exist. But it's also not convenient because I can't just copy an existing progression, as:
Copy code
val p = 5 downTo 2 step 2

val p2 = p.first .. p.last step p.step
is illegal, as the
step
function only allows positive steps (even though the progression does store it as negative). So far my best one is
Copy code
val normalizedRange = IntProgression.fromClosedRange(
	rangeStart = range.first.coerceIn(elements.indices),
	rangeEnd = range.last.plus(if (range.step > 0) 1 else -1).coerceIn(elements.indices),
	step = if (range.step > 0) range.step else -range.step,
)
but that's quite verbose (and I'm not sure it's correct)
y
I think the operation you're looking for is range intersection. It probably should be added to stdlib. I can't tell if your implementation is correct or not.
c
Yeah, that's what I'm searching for.
e
Rust
Copy code
..   ≅ (Unbounded,   Unbounded)
1..   ≅ (Included(1), Unbounded)
 ..5  ≅ (Unbounded,   Excluded(5))
 ..=4 ≅ (Unbounded,   Included(4))
1..5  ≅ (Included(1), Excluded(5))
1..=4 ≅ (Included(1), Included(4))
can express many types of ranges (and while there's no dedicated syntax for a range with an excluded start bound, it's possible by just writing the tuple). then when you use a range to slice a vector or array, any unbounded ends are clamped to the first or last index. I wish we had something like that instead of just ad-hoc ClosedRange and OpenEndRange
and I do think it's valuable to distinguish between "slicing to the end (whatever it may be)" and "slicing to an index past the end" which should be an error, just like indexing past the end is
as far as range intersection goes, that gets tricky when
step
is involved… I haven't tested your code but
rangeStart
doesn't look right for negative steps