Почему putStrLn из zio не вывел - PullRequest
1 голос
/ 05 апреля 2020

Почему 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 Ответ

5 голосов
/ 05 апреля 2020

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

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

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

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

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

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

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

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

...