简体   繁体   English

当使用scalaz-stream中的“ halt”时,“ wye”组合器的副作用

[英]side-effects for `wye` combinators when using `halt` from scalaz-stream

filter (which uses halt inside) terminates other branch even if it has some side-effects: filter (内部使用halt )终止其他分支,即使它有一些副作用:

scala> val p = Process("1","2", "3")
scala> val p1 = p.filter(_ => true).map(_ + "p1").observe(io.stdOutLines)
scala> val p2 = p.filter(_ => false).map(_ + "p2").observe(io.stdOutLines)
scala> (p1 yip p2).run.run
1p1

scala> val p2 = p.filter(_ => true).map(_ + "p1").observe(io.stdOutLines)
scala> (p1 yip p2).run.run
1p1
1p2
2p1
2p2
3p1
3p2

Seems logical as there is no value to be returned to yip after that filter . 似乎合乎逻辑,因为在该filter之后没有值要返回到yip But what about side-effects, specified with observe ? 但是observe的副作用呢?

My current solution is to use flatMap to specify default value: 我当前的解决方案是使用flatMap指定默认值:

scala> val p1 = p.map(_ + "p1").flatMap(x => Process.emit(x).observe(io.stdOutLines))

scala> val p2 = p.map(_ + "p2").flatMap(x => Process.emit(""))

scala> (p1 yip p2).run.run
1p1
2p1
3p1

But maybe there is a way to use filter ? 但是也许有一种使用filter吗?

PS merge combinator executes side-effects for other branch (as it doesn't require value to be returned), but it doesn't wait for other branch if one halts (even if it has side-effects). PS merge组合器为其他分支执行副作用(因为它不需要返回值),但是如果一个分支暂停,它就不会等待其他分支(即使它具有副作用)。

To run the effects even after p2 terminates there needs to be clear default behaviour. 即使在p2终止后也要运行效果,需要明确的default行为。 So there are probably these solutions: 因此,可能有以下解决方案:

  1. define p2 to supply default value after being terminated 定义p2以在终止后提供默认值
  2. use either wye to get left and rights if we don't really need tuples 如果我们真的不需要元组,请使用either来获得权利

perhaps the (1) is closer to question and code will looks like: 也许(1)更接近问题,代码看起来像:

val p = Process("1","2", "3")
val p1 = p.filter(_ => true).map(_ + "p1").observe(io.stdOutLines)
val p2 = p.filter(_ => false).map(_ + "p2")
         .observe(io.stdOutLines).map(Some(_)) ++ emit(None).repeat
// alternativelly
// val p2 = p.map { v =>  if (pred(v)) right(v) else left(v) }
//          .observeO(o.stdOutLines).flatMap { _.toOption }
//          ++ emit(None).repeat             

(p1 yip p2).run.run

Actually it should be just something like that: 实际上,应该是这样的:

in.map(emit).flatMap{ p =>
  val p1 = p.map(_ + "p1").filter(_ => true).observe(out)
  val p2 = p.map(_ + "p2").filter(_ => false).observe(out)
  p1 merge p2
}.run.run

It makes all side effects being in order as filter can't get more than one value (produced by emit) 它使所有副作用都井井有条,因为filter不能获得一个以上的值(由发出产生)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM