What is the best way to implement the “first success” in Scala (i.e., return the first success from the failover sequence)

There are several reasonable and idiomatic ways in the header that, as I know, return the first successful calculations, although I am most interested in how to deal with this case, when we want to know the specific failure, the last attempt, when all attempts fail. As a first attempt, we can use collectFirstand do something like the following:

  def main(args: Array[String]) {
    val xs = (1 to 5)
    def check(i: Int): Try[Int] = {
      println(s"checking: $i")
      Try(if (i < 3) throw new RuntimeException(s"small: $i") else i)
    }
    val z = xs.collectFirst { i => check(i) match { case s @ Success(x) => s } }
    println(s"final val: $z")
  }

This seems like a reasonable solution if we don't care about failures (in fact, since we always return success, we never return Failure, but only Noneif there is no successful calculation).

, , , , :

  def main2(args: Array[String]) {
    val xs = (1 to 5)
    def check(i: Int): Try[Int] = {
      println(s"checking: $i")
      Try(if (i < 3) throw new RuntimeException(s"small: $i") else i)
    }
    val empty: Try[Int] = Failure(new RuntimeException("empty"))
    val z = xs.foldLeft(empty)((e, i) => e.recoverWith { case _ => check(i) })
    println(s"final val: $z")
  }

, "" Throwable, , , , , , , -ops.

main2, ?

+4
2

- :

  @tailrec
  def collectFirstOrFailure[T](l: List[T], f: T => Try[T]): Try[T] = {
    l match {
      case h :: Nil =>  f(h)
      case h :: t =>  // f(h) orElse collectFirstOrFailure(t, f) //wish I could do this but not tailrec approved!
        val res = f(h)
        if (res.isFailure){
          collectFirstOrFailure(t, f)
        }
        else {
          res
        }
      case Nil => Failure(new RuntimeException("empty"))
    }
  }

  val y = collectFirstOrFailure(xs.toList, check)
  println(s"final val: $y")

, , Failure(new RuntimeException("empty")) ( ), , . , scalaz , . .

UPDATE

iterator...

  def collectFirstOrFailureI[T](i: Iterator[T], f: T => Try[T]): Try[T] = {
    while (i.hasNext){
      val res = f(i.next())
      if (res.isSuccess || !i.hasNext){
        return res
      }
    }
    Failure(new RuntimeException("empty"))
  }

  xs.toIterator

  val x = collectFirstOrFailureI(xs.iterator, check)
  println(s"final val: $x")
+2

:

fooobar.com/questions/170817/...

, , .

, ?

:

def bad(f: Failure) = if (count.decrementAndGet == 0) { p tryComplete new Failure(new RuntimeException("All bad", f.exception)) }

p tryComplete f
+1

Source: https://habr.com/ru/post/1545926/


All Articles