https://kotlinlang.org logo
#announcements
Title
# announcements
k

kovrik

11/07/2017, 4:31 AM
Hi! kotlin.sequences package has a flatten method (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/flatten.html). But it works only on a sequence of sequences (Sequence<Sequence<T>>). Are there any alternatives that will work on any sequence (Sequence<T>)? Something that behaves more like a flatten function in Clojure.
o

orangy

11/07/2017, 7:21 AM
I’m not sure what you think it should do? flatten gets inner sequences and joins (flattens) them together. Like
( (1,2), (3,4) )
to
(1,2,3,4)
. For a generic T, what should it do?
k

kovrik

11/07/2017, 7:32 AM
For a sequence of (1,2,3,4) it should return (1,2,3,4), which is already flat.
Basically, I want the same thing as Clojure’s flatten: user=> (flatten [1 2 3 4]) (1 2 3 4) user=> (flatten [1 [2 [3] 4] 5]) (1 2 3 4 5)
o

orangy

11/07/2017, 7:40 AM
That’s get us into a land of dynamic typing, no?
k

kovrik

11/07/2017, 7:44 AM
Well, kind of. It just becomes Sequence<Any?> as we don’t know (anymore) if given seq element is another sequence or some other object. But that is fine by me, in that particular case I’d be happy with Sequence<Any?>
It is quite a common thing to do for, say, Collections, Lists: private fun <E> flatten(list: List<E>) = mutableListOf<E>().apply { val queue = LinkedList(list) while (!queue.isEmpty()) { val e = queue.remove() when (e) { is List<*> -> queue.addAll(e as List<E>) else -> add(e) } } } This works just fine (apart from 1 unchecked cast) for any collection of any elements. I’d like to implement the same thing, but for Sequences
My initial thought was: oh, that is an easy thing to do, just replace all List in the method above with Sequence:
Copy code
private fun flatten(seq: Sequence<Any?>) = mutableListOf<Any?>().apply {
        val queue = LinkedList<Any?>().apply { addAll(seq); }
        while (!queue.isEmpty()) {
            val e = queue.remove()
            when (e) {
                is Sequence<*> -> queue.addAll(e)
                else -> add(e)
            }
        }
    }
But this doesn’t work as expected
Copy code
println(flatten(listOf(1, listOf(2, 3).asSequence(), 4).asSequence()))   // prints [1, 4, 2, 3], not [1, 2, 3, 4]
o

orangy

11/07/2017, 8:08 AM
Well, again, there is no such function in standard library. You can easily write your own 🙂
k

kovrik

11/07/2017, 8:09 AM
yeah, just wanted to confirm. Anyway, thanks for help! 🙂