Is it possible to do tail-recursion on a method which returns ZIO?

Viewed 561

For example:

def foo(bar: String): UIO[String] = {
    for {
      f <- UIO("baz")
      res <- foo(f)
    } yield res
  }

seems like that it's impossible because the last line is a mapping function

1 Answers

You can rewrite your function

def foo(bar: String): UIO[String] = {
  for {
    f <- UIO[String]("baz")
    res <- foo(f)
  } yield res
}

as

def foo(bar: String): UIO[String] = {
  UIO[String]("baz").flatMap(f =>
    foo(f)
  )
}

without extra .map.

It's clear that your function is not tail-recursive.

If you're interested in stack safety you can use scala.util.control.TailCalls, cats.free.Trampoline or cats.Monad#tailRecM

import cats.Monad
import zio.UIO
import zio.interop.catz.core._

Monad[UIO].tailRecM(??? /* starting value */)(a => ??? /* effectful calculation to be repeated until it returns Right */)

There were troubles with implementation of tailRecM for ZIO but currently the issue is closed.

Related