Почему putStrLn из zio не выводил

Почему putStrLn в flatMap, за которым следует оператор результата, не эффективно записывается в stdout?

object Mgr extends App {

  def main1(args: Array[String]) = getStrLn.flatMap { s =>
    putStrLn(s)  // Why this did not write to console?
     UIO.succeed(s)
  }

  override def run(args: List[String]): URIO[zio.ZEnv, Int] = main1(Array()).fold(_ => 1,
    { x =>
       println(x)  // only this line wrote to console, why?
      0
    })
}

1 ответ

Решение

Ваша проблема в том, что вы помещаете два эффекта в одну flatMap.

Призывая putStrLn(s) вы на самом деле не печатаете на консоль, вы просто создаете описание действия, которое будет печататься, когда ваша программа интерпретируется и запускается (когда метод runназывается). И потому что в вашей плоской карте возвращается только последнее значение (в вашем случаеUIO.succeed(s)), то только он будет учтен при построении программы ZIO.

Вы можете исправить свою программу, объединив оба действия.

Вы можете сделать это с *> оператор:

def main1(args: Array[String]) = getStrLn.flatMap { s =>
    putStrLn(s)  *>  UIO.succeed(s)
}

или вы можете просто поместить эффекты в отдельные плоские карты. Но поскольку вы хотите создать побочный эффект (путем печати значения), но затем передать значение без изменений, вам необходимо использовать специальную функциюtap:

def main1(args: Array[String]) = getStrLn.tap { s =>
    putStrLn(s)
}.flatMap { s =>
    UIO.succeed(s)
}

Ваша проблема также описана (с другими подводными камнями) в этой замечательной статье (посмотрите на первый пункт).

Другие вопросы по тегам