Jacob K
02/08/2023, 9:12 AMSam
02/08/2023, 9:13 AMChannelIterator
has suspending hasNext
(but non-suspending next
)Jacob K
02/08/2023, 9:16 AMSam
02/08/2023, 9:18 AMfor/in
is based on operator function conventions, not interfaces. So anything which has operator fun next
and operator fun hasNext
is an iterator, and anything that has operator fun iterator
is iterablesuspend
Jacob K
02/08/2023, 9:19 AMSam
02/08/2023, 9:20 AMFlow
, thoughJacob K
02/08/2023, 9:21 AMSam
02/08/2023, 9:21 AMJacob K
02/08/2023, 9:23 AMwhile (tree.hasNext()) {
val node = tree.next()
// do more supending stuff or break
}
Couldn't really figure out how that looks with flowsSam
02/08/2023, 9:28 AMflow {
while(tree.hasNext()) emit(tree.next())
}.takeWhile { node ->
// do more suspending stuff or return false
}.collect()
Jacob K
02/08/2023, 9:30 AMSam
02/08/2023, 9:34 AMJohann Pardanaud
02/08/2023, 9:38 AMJacob K
02/08/2023, 9:38 AMcollect()
is slightly ugly though, since I'm not really collecting anything and I only want the "onEach" behavior.Johann Pardanaud
02/08/2023, 9:40 AMSequence
and yield
: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/-sequence-scope/yield.htmlCLOVIS
02/08/2023, 9:51 AMFlow
is essentially the same as Sequence
with a few bonus features (suspend
, onCompletion
/`onStart` /…)Jacob K
02/08/2023, 10:04 AMCLOVIS
02/08/2023, 10:05 AMsuspend
in Sequence is not a "real" suspend
. You need to use Flow from KotlinX.CoroutinesJacob K
02/08/2023, 10:10 AMCLOVIS
02/08/2023, 10:12 AMSequence
is essentially a rewrite of Iterable
, Flow
is sequence + suspend
, and you said you wanted an iterator with suspend
.Jacob K
02/08/2023, 10:22 AMwalker.ancestors()
returning an iterator-esque thing that can be used like an iterator typically would.
The above would only be used in suspending methods and the work to traverse the tree is also suspending.
One option seems to be to return anything that has a `suspend next()`and suspend hasNext()
(no help from std lib to implement that - cmp. AbstractIterator with computeNext()
)
The other option would be to have ancestors()
return a "Flow of ancestors". To consume that I would need to use something like ancestors().takeWhile { // process or return null to stop traverseal }.collect()
(still not sure I understand if it was possible to emit items lazily, one at a time, in the flow example above)
I'm not sure what I want, but it's really interesting to learn the options. Whatever would be most idiomatic is probably preferable ;)CLOVIS
02/08/2023, 10:25 AM.map
(once it's flattened, you can't transform it back into a tree using the stdlib). If you want to keep the structure, you'll have to create your own map
etc implementation.