目标是延迟评估停止并返回第一个满意结果的函数集合。计算应该是顺序的。这是我的尝试
def f1(i: Int): Either[String, Int] = {println(s"f1($i)"); Left("boom-f1") }
def f2(i: Int): Either[String, Int] = {println(s"f2($i)"); Left("boom-f2") }
def f3(i: Int): Either[String, Int] = {println(s"f3($i)"); Right(i) }
val in = 42
(f1(in) #:: f2(in) #:: f3(in) #:: Stream.empty) collectFirst { case Right(x) => x } toRight("boom")
输出
f1(42)
f2(42)
f3(42)
res0: Either[String,Int] = Right(42)
我们看到所有三个都被处决,同时
def f1(i: Int): Either[String, Int] = {println(s"f1($i)"); Right(i) }
def f2(i: Int): Either[String, Int] = {println(s"f2($i)"); Right(i) }
def f3(i: Int): Either[String, Int] = {println(s"f3($i)"); Right(i) }
会输出
f1(42)
res0: Either[String,Int] = Right(42)
我们只看到一个被处决的地方。
猫是否为这种懒惰的失败偏向遍历提供抽象?
最佳答案
您可以使用Ior数据类型是两种数据类型之间的包含或关系。
import cats.data.Ior
import cats.implicits._
import scala.annotation.tailrec
object Main2 {
def main(args: Array[String]) : Unit = {
def f1(i: Int): Either[String, Int] = {println(s"f1($i)"); Left("boom-f1") }
def f2(i: Int): Either[String, Int] = {println(s"f2($i)"); Left("boom-f2") }
def f3(i: Int): Either[String, Int] = {println(s"f3($i)"); Right(i) }
def traverseLazy(input: Int, list: List[Int => Either[String, Int]]): Ior[List[String], Int] = {
@tailrec
def go(ls: List[Int => Either[String, Int]], acc: List[String]): Ior[List[String], Int] = ls match {
case x :: xs => x(input) match {
case Left(error) => go(xs, error :: acc)
case Right(value) => if (ls.isEmpty) value.rightIor else Ior.both(acc, value)
}
case Nil => acc.leftIor
}
go(list, List.empty)
}
val res = traverseLazy(42, List(f1, f2, f3)).fold(
_.intercalate("\n"),
res => s"succeeded with $res",
(errors, res) => s"completed successfully with res $res but some errors were also found: ${errors.intercalate(", ")}")
println(res)
}
}
关于scala - 延迟遍历首次成功时短路的函数集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58035836/