If I change my recursive call to ```!effect { ioRe...
# arrow
m
If I change my recursive call to
Copy code
!effect { ioRecurseNTimes(n - 1) }.bind()
, I don't get a stack overflow but everything seems to slow down and my CPU starts to work really hard after about 400k recursions.
p
!effect { ioRecurseNTimes(n - 1) }.bind()
this is redundant code, you’re packing and unpacking something needlessly
ioRecurseNTimes(n - 1).bind()
or
!ioRecurseNTimes(n - 1)
does the same
remember that, unlike kx.coroutines, IO is lazy and doesn’t start until you execute it with bind
IO { explosion() }
never explodes
effect { explosion() }
never explodes either
IO { explosion() }.bind()
explodes, and so does
effect { explosion() }
, in exactly the same way
So you’re doing those extra operations on top of suspend functions, which are already expensive af
re-reading why it stack overflows
that extra IO wrapper may prevent the bad coroutine rewrite
r
this is going away with the comprehensions plugins since binding and fx is no longer based in suspension but on a rewrite to flatMap
try to write the same using flatMap instead of bind and see if it stack overflows
if it does then we have a problem in the IO loop
m
Sure, I'll give it ago
r
thanks!
though the benchmarks have test for very deep binds
m
Copy code
fun ioRecurseNTimes(n: Int): IO<Unit> = IO.fx {
    if (n % 100_000 == 0) println(n)

    if (n == 0)
        Unit
    else
        ioRecurseNTimes(n - 1).bind()
}

fun ioRecurseNTimesFlatMap(n: Int): IO<Unit> {
    if (n % 1_000_000 == 0) println(n)

    if (n == 0)
        return IO.just(Unit)
    else
        return IO.just(n - 1).flatMap { ioRecurseNTimesFlatMap(it) }
}
The first one dies with a stack overflow, the second does not. I'm guessing this is the kind of transform you were thinking of?
And sorry, I should say, I'm using n = 1 billion to test.
tailrecM is working for me though 🙂
👍🏼 1