2
votes

I've got a java method visitChildrenRecursively(Node root, NodeVisitor p) that allows me to iterate over elements of a tree-like structure by providing a SAM visitor.

I'd like to convert this approach to a Sequence-based iteration.

However, this code...

buildSequence {
    visitChildrenRecursively(root, NodeVisitor {
        yield(it)
    })
}

...fails compilation with error Suspension functions can be called only within coroutine body at line yield(it)

The Kotlin coroutines Informal description suggests my visitChildrenRecursively could be converted to a suspending function by wrapping it inside a suspendCoroutine block.

Would that be the correct approach, or is this even possible without resorting to a produce approach from kotlinx as shown in the kotlinx coroutines guide ?

I also tried section "Asynchronous sequences" in the Informal description, with no luck.

1

1 Answers

2
votes

I'm afraid you're asking for the impossible. Kotlin doesn't implement coroutines through some backdoor JVM magic, but through the transformation of regular Java methods. Suspendable functions involve a hidden method signature change and their return type changes as well. Where your Visitor may have a method

void visit(Node)

this would have to become

Object visit(Node, Continuation)

Even if we pretend this is possible, your next barrier would be visitChildrenRecursively() which has no knowledge of the special contract for suspendable functions. They require the caller to pass in its continuation for a normal call and their own continuation for a resuming call. They return COROUTINE_SUSPENDED when suspended, and the caller must return the same value itself if it gets it.

If you can copy-paste the implementation of visitChildrenRecursively() and migrate it to Kotlin, then you might have a chance to succeed.