Break loop if Either function returns 左
Break loop if Either function returns Left
在下面的代码中,如果 either1
或 either2
return 离开,我需要停止处理循环,如果发生这种情况,则 mainFunction
有to return 左也。此外,由 either1.Left
或 either2.Left
编辑的字符串 return 需要由 mainFunction.Left
编辑 return。如何实现?
def either1 (i:Int): Future[Either[String,Int]] = Future {
if (i<3)
Right(i*2)
else
Left("error 1")
}
def either2 (i:Int): Future[Either[String,Int]] = Future {
if (i>3)
Right(i*2)
else
Left("error 2")
}
val seq = Seq ( 1,1,2,2,3,4,5 )
def mainFunction: Future[Either[String,Int]] = Future {
val seq2 = seq.map { number =>
if (number % 2 == 0)
either1(number) // <-- this needs to break the loop if it returns Left
else
either2(number) // <-- this needs to break the loop if it returns Left
}
Right(seq2.length) // <-- seq2 is a sequence of Futures
}
在 Scala 中,标准集合不为此提供方法。
您可以使用 scala.util.control.Breaks 或者您必须编写
递归,像这样
val seq = Seq(1, 1, 2, 2, 3, 4, 5)
def either1(i: Int): Either[String, Int] = {
if (i < 3) Right(i * 2)
else Left("error 1")
}
def either2(i: Int): Either[String, Int] = {
if (i > 3) Right(i * 2)
else Left("error 2")
}
def rec(seq: Seq[Int], acc: Seq[Either[String, Int]]): Seq[Either[String, Int]] = seq match {
case Nil => acc
case x :: xs =>
val xx = if (x % 2 == 0) either1(x) else either2(x)
xx match {
case Left(_) => acc
case Right(value) => rec(xs, acc :+ Right(value))
}
}
rec(seq, Seq())
下面的代码不断迭代序列,直到遇到第一个错误,returns 错误消息,或固定数字 42
(即 "doesn't matter what it returns"-要求) .
import scala.concurrent._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global
def either1(i: Int): Future[Either[String,Int]] = Future {
if (i < 3) Right(i * 2)
else Left("error 1")
}
def either2 (i:Int): Future[Either[String,Int]] = Future {
if (i > 3) Right(i * 2)
else Left("error 2")
}
val seq = Seq(1, 1, 2, 2, 3, 4, 5)
val doesntMatter = 42
/** Returns either first error message returned by `either1` or
* `either2`, or the fixed number `doesntMatter`.
*/
def mainFunction: Future[Either[String, Int]] = {
def recHelper(remaining: List[Int]): Future[Either[String, Int]] = {
remaining match {
case Nil => Future { Right(doesntMatter) }
case h :: t => (if (h % 2 == 0) either1(h) else either2(h)).flatMap {
headEither =>
headEither match {
case Left(s) => Future { Left(s) }
case Right(n) => recHelper(t)
}
}
}
}
recHelper(seq.toList)
}
val res = mainFunction
Thread.sleep(2000)
println(res) // Future(Success(Left(error 2)))
如果您多次执行此操作,请考虑查看 Scala Cats' EitherT,以及专门为所有 monadic 类型类上的此类用例定义的方法 tailRecM
。
如果库函数可以满足我的要求,我通常会避免使用递归函数。
在这种情况下,我们可以使用 takeWhile
获取所有 Right
的前导元素。然而,map
调用仍将处理 Seq
的每个元素,因此您需要使用 view
来懒惰地评估它:
val seq2 = seq.view.map { number =>
if (number % 2 == 0)
either1(number)
else
either2(number)
}.takeWhile(_.isRight)
您的问题仍然存在,您的 either
实际上在 return 和 Future
上运行,因此无法测试 Left
或 Right
直到他们完成。
在下面的代码中,如果 either1
或 either2
return 离开,我需要停止处理循环,如果发生这种情况,则 mainFunction
有to return 左也。此外,由 either1.Left
或 either2.Left
编辑的字符串 return 需要由 mainFunction.Left
编辑 return。如何实现?
def either1 (i:Int): Future[Either[String,Int]] = Future {
if (i<3)
Right(i*2)
else
Left("error 1")
}
def either2 (i:Int): Future[Either[String,Int]] = Future {
if (i>3)
Right(i*2)
else
Left("error 2")
}
val seq = Seq ( 1,1,2,2,3,4,5 )
def mainFunction: Future[Either[String,Int]] = Future {
val seq2 = seq.map { number =>
if (number % 2 == 0)
either1(number) // <-- this needs to break the loop if it returns Left
else
either2(number) // <-- this needs to break the loop if it returns Left
}
Right(seq2.length) // <-- seq2 is a sequence of Futures
}
在 Scala 中,标准集合不为此提供方法。 您可以使用 scala.util.control.Breaks 或者您必须编写 递归,像这样
val seq = Seq(1, 1, 2, 2, 3, 4, 5)
def either1(i: Int): Either[String, Int] = {
if (i < 3) Right(i * 2)
else Left("error 1")
}
def either2(i: Int): Either[String, Int] = {
if (i > 3) Right(i * 2)
else Left("error 2")
}
def rec(seq: Seq[Int], acc: Seq[Either[String, Int]]): Seq[Either[String, Int]] = seq match {
case Nil => acc
case x :: xs =>
val xx = if (x % 2 == 0) either1(x) else either2(x)
xx match {
case Left(_) => acc
case Right(value) => rec(xs, acc :+ Right(value))
}
}
rec(seq, Seq())
下面的代码不断迭代序列,直到遇到第一个错误,returns 错误消息,或固定数字 42
(即 "doesn't matter what it returns"-要求) .
import scala.concurrent._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global
def either1(i: Int): Future[Either[String,Int]] = Future {
if (i < 3) Right(i * 2)
else Left("error 1")
}
def either2 (i:Int): Future[Either[String,Int]] = Future {
if (i > 3) Right(i * 2)
else Left("error 2")
}
val seq = Seq(1, 1, 2, 2, 3, 4, 5)
val doesntMatter = 42
/** Returns either first error message returned by `either1` or
* `either2`, or the fixed number `doesntMatter`.
*/
def mainFunction: Future[Either[String, Int]] = {
def recHelper(remaining: List[Int]): Future[Either[String, Int]] = {
remaining match {
case Nil => Future { Right(doesntMatter) }
case h :: t => (if (h % 2 == 0) either1(h) else either2(h)).flatMap {
headEither =>
headEither match {
case Left(s) => Future { Left(s) }
case Right(n) => recHelper(t)
}
}
}
}
recHelper(seq.toList)
}
val res = mainFunction
Thread.sleep(2000)
println(res) // Future(Success(Left(error 2)))
如果您多次执行此操作,请考虑查看 Scala Cats' EitherT,以及专门为所有 monadic 类型类上的此类用例定义的方法 tailRecM
。
如果库函数可以满足我的要求,我通常会避免使用递归函数。
在这种情况下,我们可以使用 takeWhile
获取所有 Right
的前导元素。然而,map
调用仍将处理 Seq
的每个元素,因此您需要使用 view
来懒惰地评估它:
val seq2 = seq.view.map { number =>
if (number % 2 == 0)
either1(number)
else
either2(number)
}.takeWhile(_.isRight)
您的问题仍然存在,您的 either
实际上在 return 和 Future
上运行,因此无法测试 Left
或 Right
直到他们完成。