Break loop if Either function returns Left - scala

In the following code, what I need is to stop processing the loop if either either1 or either2 return Left, and if that happens then mainFunction has to return Left as well. Also, the string returned by either1.Left or either2.Left needs to be returned by mainFunction.Left. How to make this work?
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
}

The code below keeps iterating over the sequence until it encounters the first error, and returns the error message, or the fixed number 42 (that's the "doesn't matter what it returns"-requirement).
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)))
If you do this significantly more often than once, consider taking a look at Scala Cats' EitherT, and also at the method tailRecM defined specifically for such use cases on all monadic typeclasses.

In Scala the standard collections don’t provide a method for that.
You can user either scala.util.control.Breaks or you have to write the
recursion, something like this
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())

I generally avoid recursive functions if a library function will do what I want.
In this case we can use takeWhile to take all the leading elements that are Right. However the map call will still process every element of the Seq so you need to use view to evaluate this lazily:
val seq2 = seq.view.map { number =>
if (number % 2 == 0)
either1(number)
else
either2(number)
}.takeWhile(_.isRight)
You still have the the problem that your either functions actually return a Future and therefore can't be tested for Left or Right until they complete.

Related

How to create an Akka Stream Source that generates items recursively

I'm trying to figure out how to create an Akka Streams source that generates many Seq[Int].
Basically, given an int n I want to generate all of the Seq[Int] of 1 to n
Here's some code that does this:
def combinations(n: Int): Seq[Seq[Int]] = {
def loop(acc: (Seq[Int], Seq[Seq[Int]]),
remaining: Seq[Int]): Seq[Seq[Int]] = {
remaining match {
case s if s.size == 1 => {
val total: Seq[Seq[Int]] = acc._2
val current: Seq[Int] = acc._1
total :+ (current :+ s.head)
}
case _ => {
for {
x <- remaining
comb <- loop((acc._1 :+ x, acc._2), remaining.filter(_ != x))
} yield comb
}
}
}
loop((Seq(), Seq()), (1 to n))
}
This works fine up to 10... then it blows up because it runs out of memory. Since I just want to process each of them and don't need to keep them all in memory, I thought... Akka Streams. But I'm at a loss for how to turn this into a Source that produces each combination so I can process them. Basically there where it's appending to total I would produce another item onto the stream.
Here is a solution that uses the Johnson-Trotter algorithm for permutations. tcopermutations creates a LazyList that can be evaluated as needed. For more permutations, just pass a different value to printNIterations.
The reason for using the Johnson-Trotter algorithm is that it breaks the recursive structure of the permutation finding algorithm. That's important for being able to evaluate successive instances of the permutation and storing them in some kind of lazy list or stream.
object PermutationsTest {
def main(args: Array[String]) = {
printNIterations(50, tcopermutations(5).iterator)
}
def printNIterations(n: Int, it: Iterator[Seq[Int]]): Unit = {
if (n<=0) ()
else {
if (it.hasNext) {
println(it.next())
printNIterations(n - 1, it)
} else ()
}
}
def naivepermutations(n: Int): Seq[Seq[Int]] = {
def loop(acc: Seq[Int], remaining: Seq[Int]): Seq[Seq[Int]] = {
remaining match {
case s if s.size == 1 => {
val current: Seq[Int] = acc
Seq((current :+ s.head))
}
case _ => {
for {
x <- remaining
comb <- loop(acc :+ x, remaining.filter(_ != x))
} yield comb
}
}
}
loop(Seq(), (1 to n))
}
def tcopermutations(n: Int): LazyList[Seq[Int]] = {
val start = (1 to n).map(Element(_, Left))
def loop(v: Seq[Element]): LazyList[Seq[Element]] = {
johnsonTrotter(v) match {
case Some(s) => v #:: loop(s)
case None => LazyList(v)
}
}
loop(start).map(_.map(_.i))
}
def checkIfMobile(seq: Seq[Element], i: Int): Boolean = {
val e = seq(i)
def getAdjacent(s: Seq[Element], d: Direction, j: Int): Int = {
val adjacentIndex = d match {
case Left => j - 1
case Right => j + 1
}
s(adjacentIndex).i
}
if (e.direction == Left && i == 0) false
else if (e.direction == Right && i == seq.size - 1) false
else if (getAdjacent(seq, e.direction, i) < e.i) true
else false
}
def findLargestMobile(seq: Seq[Element]): Option[Int] = {
val mobiles = (0 until seq.size).filter{j => checkIfMobile(seq, j)}
if (mobiles.isEmpty) None
else {
val folded = mobiles.map(x=>(x,seq(x).i)).foldLeft(None: Option[(Int, Int)]){ case (acc, elem) =>
acc match {
case None => Some(elem)
case Some((i, value)) => if (value > elem._2) Some((i, value)) else Some(elem)
}
}
folded.map(_._1)
}
}
def swapLargestMobile(seq: Seq[Element], index: Int): (Seq[Element], Int) = {
val dir = seq(index).direction
val value = seq(index).i
dir match {
case Right =>
val folded = seq.foldLeft((None, Seq()): (Option[Element], Seq[Element])){(acc, elem) =>
val matched = elem.i == value
val newAccOpt = if (matched) Some(elem) else None
val newAccSeq = acc._1 match {
case Some(swapMe) => acc._2 :+ elem :+ swapMe
case None => if (matched) acc._2 else acc._2 :+ elem
}
(newAccOpt, newAccSeq)
}
(folded._2, index + 1)
case Left =>
val folded = seq.foldRight((None, Seq()): (Option[Element], Seq[Element])){(elem, acc) =>
val matched = elem.i == value
val newAccOpt = if (matched) Some(elem) else None
val newAccSeq = acc._1 match {
case Some(swapMe) => swapMe +: elem +: acc._2
case None => if (matched) acc._2 else elem +: acc._2
}
(newAccOpt, newAccSeq)
}
(folded._2, index - 1)
}
}
def revDirLargerThanMobile(seq: Seq[Element], mobile: Int) = {
def reverse(e: Element) = {
e.direction match {
case Left => Element(e.i, Right)
case Right => Element(e.i, Left)
}
}
seq.map{ elem =>
if (elem.i > seq(mobile).i) reverse(elem)
else elem
}
}
def johnsonTrotter(curr: Seq[Element]): Option[Seq[Element]] = {
findLargestMobile(curr).map { m =>
val (swapped, newMobile) = swapLargestMobile(curr, m)
revDirLargerThanMobile(swapped, newMobile)
}
}
trait Direction
case object Left extends Direction
case object Right extends Direction
case class Element(i: Int, direction: Direction)
}

Recursively returning a concatenation of Future.Right

In the recursive recHelper method below I need to return a list of Futures if all the elements returned Right else a Future Left. Problem is that I cannot concatenate the results. How to make this code work?
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)
def recHelper(remaining: List[Int]): Future[Either[String, Seq[Int]]] = {
remaining match {
case Nil => Nil
case h :: t => (if (h % 2 == 0) either1(h) else either2(h)).map {
headEither =>
headEither match {
case Left(s) => Future { Left(s) }
case Right(n) => Future { n :: recHelper(t) :: Nil } /// ERROR
}
}
}
}
recHelper(seq.toList)
The Nil => Nil case indicates that you should read up again what the Future and what the Either monads do: Nil is inferred to be of type List[Int]. It's missing two applications of a monadic unit, namely:
You forgot to wrap it into a Right to make it Either[List[Int]]
You forgot to wrap it into a Future, to make it Future[Either[List[Int]]
Same applies for the other cases. Here is a version that works:
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)
def recHelper(remaining: List[Int]): Future[Either[String, List[Int]]] = {
remaining match {
case Nil => Future { Right(Nil) }
case h :: t => for {
hEith <- (if (h % 2 == 0) either1(h) else either2(h))
res <- (hEith match {
case Left(s) => Future { Left(s) }
case Right(n) => for {
tEith <- recHelper(t)
} yield tEith.map(n :: _)
})
} yield res
}
}
recHelper(seq.toList)
You can't build a complex nested for-comprehension with two stacked monads by accident. I can only again strongly recommend to take a look at Scala Cats and EitherT. They've build the monad transformer libraries not (only) for fun: it's actually quite painful to deal with two stacked monads simultaneously.
An alternate solution:
def recHelper(remaining :Seq[Int]
,acc :Seq[Int] = Seq()
) :Future[Either[String, Seq[Int]]] = remaining match {
case Seq() => Future(Right(acc))
case h +: t => (if (h % 2 == 0) either1(h) else either2(h)).flatMap {
case Left(s) => Future(Left(s))
case Right(n) => recHelper(t, n +: acc)
}
}
recHelper(seq)
//res0: Future[Either[String,Seq[Int]]] = Future(Right(List(4, 4, 2, 2)))

Scala generic "string split" method

If I were splitting a string, I would be able to do
"123,456,789".split(",")
to get
Seq("123","456","789")
Thinking of a string as a sequence of characters, how could this be generalized to other sequences of objects?
val x = Seq(One(),Two(),Three(),Comma(),Five(),Six(),Comma(),Seven(),Eight(),Nine())
x.split(
number=>{
case _:Comma => true
case _ => false
}
)
split in this case doesn't exist, but it reminds me of span, partition, groupby, but only span seems close, but it doesn't handle leading/ending comma's gracefully.
implicit class SplitSeq[T](seq: Seq[T]){
import scala.collection.mutable.ListBuffer
def split(sep: T): Seq[Seq[T]] = {
val buffer = ListBuffer(ListBuffer.empty[T])
seq.foreach {
case `sep` => buffer += ListBuffer.empty
case elem => buffer.last += elem
}; buffer.filter(_.nonEmpty)
}
}
It can be then used like x.split(Comma()).
The following is 'a' solution, not the most elegant -
def split[A](x: Seq[A], edge: A => Boolean): Seq[Seq[A]] = {
val init = (Seq[Seq[A]](), Seq[A]())
val (result, last) = x.foldLeft(init) { (cum, n) =>
val (total, prev) = cum
if (edge(n)) {
(total :+ prev, Seq.empty)
} else {
(total, prev :+ n)
}
}
result :+ last
}
Example result -
scala> split(Seq(1,2,3,0,4,5,0,6,7), (_:Int) == 0)
res53: Seq[Seq[Int]] = List(List(1, 2, 3), List(4, 5), List(6, 7))
This is how I've solved it in the past, but I suspect there is a better / more elegant way.
def break[A](xs:Seq[A], p:A => Boolean): (Seq[A], Seq[A]) = {
if (p(xs.head)) {
xs.span(p)
}
else {
xs.span(a => !p(a))
}
}

How to best implement "first success" in Scala (i.e., return the first success from a sequence of failure-prone operations)

Per the title, there are a couple of reasonable and idiomatic ways that I know of to return the first successful computation, though I'm most interested here in how to handle the case when we want to know the specific failure of the last attempt when all attempts fail. As a first attempt, we can use collectFirst and 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 the failures (actually, since we're always returning a success, we never return a Failure, only a None in the case there is no successful computation).
On the other hand, to handle the case when all attempts fail, we can capture the last failure by using the following:
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")
}
The disadvantages here are that you create a "fake" Throwable representing empty, and if the list is very long, we iterate over the whole list, even though we may have succeeded very early on, even if later iterations are essentially no-ops.
Is there a better way to implement main2 that is idiomatic and doesn't suffer from the aforementioned disadvantages?
You could do something like this:
#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")
This isn't very pretty, and we do still have to handle the empty list case, but we're not creating a new Failure(new RuntimeException("empty")) with every run (unless it's an empty list) and we stop short if there's a success. I feel like scalaz has some better way to do this but I can't figure it out right now. The returning the last failure requirement is making this a bit complex.
UPDATE
There's always 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")
There's a previous answer:
https://stackoverflow.com/a/20665337/1296806
with the caveat that your question asks for the last failure, if all have failed.
I guess that's why this isn't a duplicate?
That's trivial to add to the code from that answer:
def bad(f: Failure) = if (count.decrementAndGet == 0) { p tryComplete new Failure(new RuntimeException("All bad", f.exception)) }
or more simply
p tryComplete f

Cartesian product stream scala

I had a simple task to find combination which occurs most often when we drop 4 cubic dices an remove one with least points.
So, the question is: are there any Scala core classes to generate streams of cartesian products in Scala? When not - how to implement it in the most simple and effective way?
Here is the code and comparison with naive implementation in Scala:
object D extends App {
def dropLowest(a: List[Int]) = {
a diff List(a.min)
}
def cartesian(to: Int, times: Int): Stream[List[Int]] = {
def stream(x: List[Int]): Stream[List[Int]] = {
if (hasNext(x)) x #:: stream(next(x)) else Stream(x)
}
def hasNext(x: List[Int]) = x.exists(n => n < to)
def next(x: List[Int]) = {
def add(current: List[Int]): List[Int] = {
if (current.head == to) 1 :: add(current.tail) else current.head + 1 :: current.tail // here is a possible bug when we get maximal value, don't reuse this method
}
add(x.reverse).reverse
}
stream(Range(0, times).map(t => 1).toList)
}
def getResult(list: Stream[List[Int]]) = {
list.map(t => dropLowest(t).sum).groupBy(t => t).map(t => (t._1, t._2.size)).toMap
}
val list1 = cartesian(6, 4)
val list = for (i <- Range(1, 7); j <- Range(1,7); k <- Range(1, 7); l <- Range(1, 7)) yield List(i, j, k, l)
println(getResult(list1))
println(getResult(list.toStream) equals getResult(list1))
}
Thanks in advance
I think you can simplify your code by using flatMap :
val stream = (1 to 6).toStream
def cartesian(times: Int): Stream[Seq[Int]] = {
if (times == 0) {
Stream(Seq())
} else {
stream.flatMap { i => cartesian(times - 1).map(i +: _) }
}
}
Maybe a little bit more efficient (memory-wise) would be using Iterators instead:
val pool = (1 to 6)
def cartesian(times: Int): Iterator[Seq[Int]] = {
if (times == 0) {
Iterator(Seq())
} else {
pool.iterator.flatMap { i => cartesian(times - 1).map(i +: _) }
}
}
or even more concise by replacing the recursive calls by a fold :
def cartesian[A](list: Seq[Seq[A]]): Iterator[Seq[A]] =
list.foldLeft(Iterator(Seq[A]())) {
case (acc, l) => acc.flatMap(i => l.map(_ +: i))
}
and then:
cartesian(Seq.fill(4)(1 to 6)).map(dropLowest).toSeq.groupBy(i => i.sorted).mapValues(_.size).toSeq.sortBy(_._2).foreach(println)
(Note that you cannot use groupBy on Iterators, so Streams or even Lists are the way to go whatever to be; above code still valid since toSeq on an Iterator actually returns a lazy Stream).
If you are considering stats on the sums of dice instead of combinations, you can update the dropLowest fonction :
def dropLowest(l: Seq[Int]) = l.sum - l.min