2

I have a simple for-comprehension code:

def nameFormatter(request: SomeRequest) : FormattedData = {
      for {
        config <- ZIO.fromOption(configuration.get(request.name)).orElseFail( new Exception("Unknown config"))
        name = config.data.name.pipe(SomeName)
      } yield FormattedData(
        name,
        request.age
      )
    }

But this method returns:

ZIO[Any, Exception, FormattedData]

I would like to change this method to return only FormattedData, not the whole ZIO. Is it possible? Or maybe I should somehow read returned type and get value from it?

Gaël J
  • 11,274
  • 4
  • 17
  • 32
Developus
  • 1,400
  • 2
  • 14
  • 50
  • 3
    May I ask, why you want to return a plain value? Integration with a third-party service? Why are you using **ZIO** at all, because it comes from a third-partly library? Do you understand the purpose of an `IO` data type? – Luis Miguel Mejía Suárez Sep 22 '21 at 15:53
  • I want pure value, because I do not need effect here – Developus Sep 22 '21 at 16:26
  • 3
    So why even use **ZIO** in the first place? Why not just `configuration.get(request.name).map(config => FormattedData(name = config.data.name.pipe(SomeName), age = request.age)` and return a `Option[FormattedData]`? – Luis Miguel Mejía Suárez Sep 22 '21 at 16:34

3 Answers3

6

ZIO makes it difficult to do this because it is unsafe and it defeats the purpose of using ZIO. You can tell from the type ZIO[Any, Exception, FormattedData] that it can fail with an Exception if you try to materialise the value.

If you really want to do it:

zio.Runtime.default.unsafeRun(nameFormatter(request))

otherwise you should be composing the rest of your code with the result of nameFormatter(request) and run it with something like:

import zio.{ExitCode, URIO, ZIO}

object Main extends zio.App {
  override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] =
    (for {
      formattedData <- nameFormatter(request)
      // rest of your code
    } yield ()).exitCode
}
yangzai
  • 962
  • 5
  • 11
0

The way to use it is

nameFormatter(request).flatMap { formattedData =>
  // whatever you want to do with the returned value
  // ...
  // the rest of your program
}

or in a for comprehension:

for {
  formattedData <- nameFormatter(request)
  // rest of your program
} yield ()

This DOES NOT answer your question, however it's probably what you wanted to do.

gurghet
  • 7,591
  • 4
  • 36
  • 63
0

Since ZIO 2.0, unsafe running an effect would be done like so:

zio.Runtime.default.unsafe.run(nameFormatter(request))

In order to work, you need to provide an implicit parameter unsafe: zio.Unsafe. This could be done like so:

Unsafe.unsafe(implicit u => zio.Runtime.default.unsafe.run(nameFormatter(request)))

See the documentation: https://zio.dev/reference/core/runtime/#running-a-zio-effect

Irina S.
  • 133
  • 8