Inspired by IntStream.iterate in modern versions o...
# announcements
w
Inspired by IntStream.iterate in modern versions of Java, I was interested in having function that would create a sequence of values that could be specified and would behave much like a classic indexed for loop. I cobbled something up using generateSequence, but I'm wondering if there is something in the actual standard library that does something close to this already...
Copy code
fun <T> iterate(seed: T, predicate: (T) -> Boolean, transform: (T) -> T): Sequence<T> {
    var current = seed
    return generateSequence() {
        if (!predicate(current)) null
        else {
            val was = current
        	current = transform(was)
            was
        }
    }
}

val seq: Sequence<Int> = iterate(0, { it < 1000 }, { it * 2 + 1 })

fun main() { println(seq.toList()) }

[0, 1, 3, 7, 15, 31, 63, 127, 255, 511]
n
I'm confused how generate sequence doesn't already do what you want?
It seems like the only difference is taking two separate lambdas as predicate + transform vs just nullable transform
e
Copy code
val seq = generateSequence(0) { it * 2 + 1 }.takeWhile { it < 1000 }
☝️ 2
w
@Nir I like the idea of being able to specify the predicate and transform separately, that's all. It makes adapting imperative code more straightforward by directly mirroring the for loop syntax.
🤔 1
@ephemient yeah, my version started out closer to yours, generateSequence with a seed always returns the seed, which a for loop won't do if the predicate fails on the initial version. I'm sure there is a better way to rephrase it, Just wanted to make sure I wasn't overlooking something in the standard lib.
e
if you don't want the seed to appear in the sequence, you could
.drop(1).takeWhile { ... }
I don't imagine it's common to want a value in the sequence which break the predicate (first value or not)
Copy code
.withIndex().filter { (index, value) -> index == 0 || ... }.map { it.value }
would let the first item pass regardless
but for the generate scenario,
Copy code
sequenceOf(seed) + generateSequence(transform(seed), transform).takeWhile(predicate)
would be clearer most of the time, IMO