package blitz.collections import blitz.Obj import blitz.Provider import kotlin.math.max fun lazySequence(vararg init: Pair, default: Obj?, f: (Int, (Int) -> T) -> T): IndexableSequence = object : IndexableSequence { val map = mutableMapOf(*init) var current: Int? = null fun comp(iIn: Int): T { val i = max(0, iIn) if (current == i) return (default ?: throw Exception("recursion detected")).v return map[i] ?: let { current = i val res = f(i, ::comp) map[i] = res current = null res } } override fun get(index: Int) = comp(index) override fun iterator(): Iterator = object : Iterator { override fun hasNext() = true private var i = 0 override fun next(): T = comp(i ++) } } fun easySequence(vararg init: Pair, f: (Int, (Int) -> T?) -> T?): Sequence = lazySequence(*init, default = Obj.of(null)) { i, ff -> f(i) { index -> var indexC = index var v: T? = null while (indexC > 0 && v == null) v = ff(indexC --) v } } fun Sequence.easyMappingSequence( vararg init: Pair, f: (Int, (Int) -> T?, (Int) -> I) -> T? ): Sequence { val indexable = this.asIndexable() return easySequence(*init) { i, ff -> f(i, ff, indexable::get) }.limitBy(indexable) .removeNull() } fun selfInitializingSequence(block: Provider>): Sequence = object : Sequence { val seq by lazy(block) inner class Iter : Iterator { val iter = seq.iterator() override fun hasNext(): Boolean = iter.hasNext() override fun next(): T = iter.next() } override fun iterator(): Iterator = Iter() }