Можно ли выполнить хвостовую рекурсию для метода, возвращающего ZIO? - PullRequest
1 голос
/ 12 июля 2020

Например:

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

кажется, что это невозможно, потому что последняя строка является функцией сопоставления

1 Ответ

1 голос
/ 12 июля 2020

Вы можете переписать свою функцию

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

как

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

без дополнительных .map.

Понятно, что ваша функция не является хвостовой рекурсивной.

Если вас интересует безопасность стека, вы можете использовать scala.util.control.TailCalls, cats.free.Trampoline или 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 */)

Там были проблемы с реализацией tailRecM для ZIO, но на данный момент проблема закрыта.

...