louiscad
07/01/2021, 9:33 PMIntRange
would be super useful. One use case is doing text/string replacement (without or with regexes).
Such code:
val offset = -matchResult.range.first
val rangeToReplaceInMatch = (urlGroup.range.first + offset)..(urlGroup.range.last + offset)
could become that one liner:
val rangeToReplaceInMatch = urlGroup.range.offset(-matchResult.range.first)
BTW, I'm doing that in a Kotlin script, where, in a way, adding extra extensions is mostly adding noise to the signal, as scripts are better short for quick understanding.ephemient
07/01/2021, 9:56 PMoperator fun IntRange.plus(offset: Int): IntRange
operator fun IntRange.minus(offset: Int): IntRange
although an infix function could work too (à la skip
)ephemient
07/01/2021, 10:00 PM(-1 .. 1).count() // => 3
(-1 .. 1).offset(Int.MIN_VALUE).count() // => 0? 2? exception?
louiscad
07/01/2021, 10:11 PMIntRange
is an IntProgression
which is Iterable
, which already has a plus
operator defined.ephemient
07/01/2021, 10:12 PMjw
07/02/2021, 12:02 AMlouiscad
07/02/2021, 5:08 AMoffset
?
About expanding an IntRange
on one or both sides, I'm wondering about your exact use cases and what names would work best for these potential new API members.ephemient
07/02/2021, 5:40 AMfun IntRange.copy(start: Int = start, endInclusive: Int = endInclusive): IntRange = start..endInclusive
doesn't seem more ergonomic thoughephemient
07/02/2021, 5:44 AMinline fun IntRange.mapMonotonic(block: (Int) -> Int): IntRange = block(start)..block(endInclusive)
range.mapMonotonic { it + offset }
but there's no way to verify that the transform is actually order-preserving, and it doesn't make sense on an IntProgression
eithermarcinmoskala
07/02/2021, 6:36 AMoperator fun IntRange.plus(offset: Int) =
IntRange(start + offset, endInclusive + offset)
operator fun IntRange.minus(offset: Int) =
IntRange(start - offset, endInclusive - offset)
fun main() {
print((1..10) + 4) // 5..14
print((1..10) - 4) // -3..6
}
ephemient
07/02/2021, 6:43 AMoperator fun <T> Iterable<T>.plus(element: T)
and IntRange
implements Iterable<Int>
louiscad
07/02/2021, 6:53 AMmarcinmoskala
07/02/2021, 7:15 AMephemient
07/02/2021, 1:57 PMZhelenskiy
07/02/2021, 4:57 PMephemient
07/02/2021, 5:21 PMshl
and shr
when that could just be negated, but shift
sounds like a reasonable name to me.
infix fun Int.plusSaturated(other: Int) = (this + other).let { result ->
if ((this < 0) != (other < 0) || (this < 0) == (result < 0)) result else if (this < 0) Int.MIN_VALUE else Int.MAX_VALUE
}
infix fun IntRange.shiftStart(x: Int) = (start plusSaturated x) .. endInclusive
infix fun IntRange.shiftEnd(x: Int) = start .. (endInclusive plusSaturated x)
infix fun IntRange.shift(x: Int) = (start plusSaturated x) .. (endInclusive plusSaturated x)
infix fun IntProgression.shiftFirst(x: Int) = (first plusSaturated x) .. last step step
infix fun IntProgression.shiftLast(x: Int) = first .. (last plusSaturated x) step step
infix fun IntProgression.shift(x: Int) = (first plusSaturated x) .. (last plusSaturated x) step step
(choosing to have 0..1 shift Int.MAX_VALUE
return Int.MAX_VALUE..Int.MAX_VALUE
instead of Int.MAX_VALUE..Int.MIN_VALUE
, neither is a great option but the latter is worse IMO)Zhelenskiy
07/02/2021, 5:38 PMZhelenskiy
07/02/2021, 5:42 PMephemient
07/02/2021, 5:47 PMZhelenskiy
07/02/2021, 5:54 PMZhelenskiy
07/02/2021, 5:56 PMephemient
07/02/2021, 5:56 PMephemient
07/02/2021, 5:57 PMZhelenskiy
07/02/2021, 5:58 PMlouiscad
07/02/2021, 7:23 PMIntRange
is not a binary concept, so shr
or shl
would be confusing and actually inconsistent.louiscad
07/02/2021, 7:25 PMshift
is too close to the binary meaning as well IMO. On the other hand, offset
is not ambiguous AFAIK, and is used in things like array copying and in graphical UI dev for similar things.Zhelenskiy
07/03/2021, 10:09 AM