Recently I needed a `forEachWithNext`, analogous t...
# stdlib
y
Recently I needed a
forEachWithNext
, analogous to
zipWithNext
. Could be a nice addition to stdlib. Here's an impl based on `zipWithNext`:
Copy code
inline fun <T> Iterable<T>.forEachWithNext(block: (a: T, b: T) -> Unit) {
    val iterator = iterator()
    if (!iterator.hasNext()) return
    var current = iterator.next()
    while (iterator.hasNext()) {
        val next = iterator.next()
        block(current, next)
        current = next
    }
}
j
That's is
windowed(2)
, no?
I'm not sure why zipWithNext isn't deprecated, actually
y
Windowed has no type-system guarantee about how many elements are in the list. It'll also result in allocating a lot of lists. zipWithNext, at least the version that takes a lambda, doesn't actually allocate anything per item. Same here with forEachWithNext. I could've just used
zipWithNext().forEach { (cur, next) -> }
or
windowed(2).forEach { (cur, next) -> }
but those objects in the middle are totally unnecessary. It's similar to how
forEachWithIndex
exists even though
withIndex().forEach
is semantically equivalent to it.
j
The problem with this approach is that there's always one more function you need to avoid a bunch of allocations in Kotlin
I would much rather see work done on local optimizations within function bodies to eliminate allocations and keep the stdlib small, similar to Rust's heavy iterator use but otherwise light runtime impact
1
y
That's a good perspective to have. Perhaps with value classes and Valhalla those optimizations will be trivial for the compiler, and thus we could have
withIndex()
and
zipWithNext()
be optimized by default, hence eliminating the need for all those extra functions. Thank you Jake!
e
windowed with lambda doesn't allocate repeatedly, it reuses (hence the documentation around "Note that the list passed to the transform function is ephemeral and is valid only inside that function. You should not store it or allow it to escape in some way, unless you made a snapshot of it.")
👀 1
👍 1
y
That's... genius! That genuinely is super helpful. Thank you!