I want to apply a function f to each element of a List and not stop at the first error but throw the last error (if any) only:
#annotation.tailrec
def tryAll[A](xs: List[A])(f: A => Unit): Unit = {
xs match {
case x :: xt =>
try {
f(x)
} finally {
tryAll(xt)(f)
}
case _ =>
}
}
But, the above code does not compile - it is complaining that this function is not tail recursive. Why not?
This solution iterates over all elements and produces (throws) the last error if any:
def tryAll[A](xs: List[A])(f: A => Unit): Unit = {
val res = xs.foldLeft(Option.empty[Throwable]) {
case (maybeThrowable, a) =>
Try(f(a)) match {
case Success(_) => maybeThrowable
case Failure(e) => Option(e)
}
}
res.foreach(throwable => throw throwable)
}
As mentioned by #HristoIliev, your method cannot be tail recursive because the finally call is not guaranteed to be the tail call. This means that any method using try in this way will not be tail recursive. See this answer, also.
Calling the method again is a weird way of trying something repeatedly until it succeeds, because at each stage it's throwing an exception you are presumably not handling. Instead, I'd argue using a functional approach with Try, taking failures from a view until the operation succeeds. The only disadvantage to this approach is that it doesn't throw any exceptions for you to handle along the way (which can also be an advantage!).
def tryAll[A](xs: List[A])(f: A => Unit): Unit =
xs.view.map(x => Try(f(x))).takeWhile(_.isFailure).force
scala> val list = List(0, 0, 0, 4, 5, 0)
scala> tryAll(list)(a => println(10 / a))
2
If you really want to handle the exceptions (or just the last exception), you can change the return type of tryAll to List[Try[Unit]] (or simply Try[Unit] if you modify the code to only take the last one). It's better for the return type of the method to describe part of what it's actually doing--potentially returning errors.
Not sure the intention of the method, but you can something like that:
final def tryAll[A](xs: List[A])(f: A => Unit): Unit = {
xs match {
case x :: xt =>
try {
f(x)
} catch {
case e => tryAll(xt)(f)
}
case _ => //do something else
}
}
I know this way to use #annotation.tailrec
From this:
def fac(n:Int):Int = if (n<=1) 1 else n*fac(n-1)
You should have this:
#scala.annotation.tailrec
def facIter(f:Int, n:Int):Int = if (n<2) f else facIter(n*f, n-1)
def fac(n:Int) = facIter(1,n)
Related
What is the idiomatic way of applying a function A => Try[B] on a List[A] and return either the first succesful result Some[B] (it short-circuits) or if everything fails, returns None
I want to do something like this:
val inputs: List[String] = _
def foo[A, B](input: A): Try[B] = _
def main = {
for {
input <- inputs
} foo(input) match {
case Failure(_) => // continue
case Success(x) => return Some(x) //return the first success
}
return None // everything failed
}
You can do the same thing using collectFirst in one less step:
inputs.iterator.map(foo).collectFirst { case Success(x) => x }
You want this:
inputs
.iterator // or view (anything lazy works)
.map(foo)
.find(_.isSuccess)
.map(_.get)
It returns an Option[B].
Here's the same thing but it will return the last Failure in the list if none are successful. Theoretically tries.find(_.isSuccess).getOrElse(tries.last) would work, but on a list view (lazy list) that causes all the attempts to be evaluated twice. Instead, this works for lazy lists (throws on empty collection):
val tries = inputs.view.map(foo)
val firstSuccessOrLastFailure = tries.zipWithIndex.collectFirst({
case (s # Success(_), _) => s
case (f, i) if (i == tries.size - 1) => f
}).get
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
I am trying to find a cleaner way to express code that looks similar to this:
def method1: Try[Option[String]] = ???
def method2: Try[Option[String]] = ???
def method3: Try[Option[String]] = ???
method1 match
{
case f: Failure[Option[String]] => f
case Success(None) =>
method2 match
{
case f:Failure[Option[String]] => f
case Success(None) =>
{
method3
}
case s: Success[Option[String]] => s
}
case s: Success[Option[String]] => s
}
As you can see, this tries each method in sequence and if one fails then execution stops and the base match resolves to that failure. If method1 or method2 succeeds but contains None then the next method in the sequence is tried. If execution gets to method3 its results are always returned regardless of Success or Failure. This works fine in code but I find it difficult to follow whats happening.
I would love to use a for comprehension
for
{
attempt1 <- method1
attempt2 <- method2
attempt3 <- method3
}
yield
{
List(attempt1, attempt2, attempt3).find(_.isDefined)
}
because its beautiful and what its doing is quite clear. However, if all methods succeed then they are all executed every time, regardless of whether an earlier method returns a usable answer. Unfortunately I can't have that.
Any suggestions would be appreciated.
scalaz can be of help here. You'll need scalaz-contrib which adds a monad instance for Try, then you can use OptionT which has nice combinators. Here is an example:
import scalaz.OptionT
import scalaz.contrib.std.utilTry._
import scala.util.Try
def method1: OptionT[Try, String] = OptionT(Try(Some("method1")))
def method2: OptionT[Try, String] = OptionT(Try(Some("method2")))
def method3: OptionT[Try, String] = { println("method 3 is never called") ; OptionT(Try(Some("method3"))) }
def method4: OptionT[Try, String] = OptionT(Try(None))
def method5: OptionT[Try, String] = OptionT(Try(throw new Exception("fail")))
println((method1 orElse method2 orElse method3).run) // Success(Some(method1))
println((method4 orElse method2 orElse method3).run) // Success(Some(method2))
println((method5 orElse method2 orElse method3).run) // Failure(java.lang.Exception: fail)
If you don't mind creating a function for each method, you can do the following:
(Try(None: Option[String]) /: Seq(method1 _, method2 _, method3 _)){ (l,r) =>
l match { case Success(None) => r(); case _ => l }
}
This is not at all idiomatic, but I would like to point out that there's a reasonably short imperative version also with a couple tiny methods:
def okay(tos: Try[Option[String]]) = tos.isFailure || tos.success.isDefined
val ans = {
var m = method1
if (okay(m)) m
else if ({m = method2; okay(m)}) m
method3
}
The foo method should do the same stuff as your code, I don't think it is possible to do it using the for comprehension
type tryOpt = Try[Option[String]]
def foo(m1: tryOpt, m2: tryOpt, m3: tryOpt) = m1 flatMap {
case x: Some[String] => Try(x)
case None => m2 flatMap {
case y: Some[String] => Try(y)
case None => m3
}
}
method1.flatMap(_.map(Success _).getOrElse(method2)).flatMap(_.map(Success _).getOrElse(method3))
How this works:
The first flatMap takes a Try[Option[String]], if it is a Failure it returns the Failure, if it is a Success it returns _.map(Success _).getOrElse(method2) on the option. If the option is Some then it returns the a Success of the Some, if it is None it returns the result of method2, which could be Success[None], Success[Some[String]] or Failure.
The second map works similarly with the result it gets, which could be from method1 or method2.
Since getOrElse takes a by-name paramater method2 and method3 are only called if they need to be.
You could also use fold instead of map and getOrElse, although in my opinion that is less clear.
From this blog:
def riskyCodeInvoked(input: String): Int = ???
def anotherRiskyMethod(firstOutput: Int): String = ???
def yetAnotherRiskyMethod(secondOutput: String): Try[String] = ???
val result: Try[String] = Try(riskyCodeInvoked("Exception Expected in certain cases"))
.map(anotherRiskyMethod(_))
.flatMap(yetAnotherRiskyMethod(_))
result match {
case Success(res) => info("Operation Was successful")
case Failure(ex: ArithmeticException) => error("ArithmeticException occurred", ex)
case Failure(ex) => error("Some Exception occurred", ex)
}
BTW, IMO, Option is no need here?
The traverse method from Future object stops at first failure. I want a tolerant/forgiving version of this method which on occurrence of errors carries on with the rest of the sequence.
Currently we have added the following method to our utils:
def traverseFilteringErrors[A, B <: AnyRef]
(seq: Seq[A])
(f: A => Future[B]): Future[Seq[B]] = {
val sentinelValue = null.asInstanceOf[B]
val allResults = Future.traverse(seq) { x =>
f(x) recover { case _ => sentinelValue }
}
val successfulResults = allResults map { result =>
result.filterNot(_ == sentinelValue)
}
successfulResults
}
Is there a better way to do this?
A genuinely useful thing (generally speaking) would be to be able to promote the error of a future into a proper value. Or in other words, transform a Future[T] into a Future[Try[T]] (the succesful return value becomes a Success[T] while the failure case becomes a Failure[T]). Here is how we might implement it:
// Can also be done more concisely (but less efficiently) as:
// f.map(Success(_)).recover{ case t: Throwable => Failure( t ) }
// NOTE: you might also want to move this into an enrichment class
def mapValue[T]( f: Future[T] ): Future[Try[T]] = {
val prom = Promise[Try[T]]()
f onComplete prom.success
prom.future
}
Now, if you do the following:
Future.traverse(seq)( f andThen mapValue )
You'll obtain a succesful Future[Seq[Try[A]]], whose eventual value contains a Success instance for each successful future, and a Failure instance for each failed future.
If needed, you can then use collect on this seq to drop the Failure instances and keep only the sucessful values.
In other words, you can rewrite your helper method as follows:
def traverseFilteringErrors[A, B](seq: Seq[A])(f: A => Future[B]): Future[Seq[B]] = {
Future.traverse( seq )( f andThen mapValue ) map ( _ collect{ case Success( x ) => x } )
}
Is there a way to turn a Seq[Future[X]] into an Enumerator[X] ? The use case is that I want to get resources by crawling the web. This is going to return a Sequence of Futures, and I'd like to return an Enumerator that will push the futures in the order in which they are first finished on to the Iteratee.
It looks like Victor Klang's Future select gist could be used to do this - though it looks pretty inefficient.
Note: The Iteratees and Enumerator's in question are those given by the play framework version 2.x, ie with the following imports: import play.api.libs.iteratee._
Using Victor Klang's select method:
/**
* "Select" off the first future to be satisfied. Return this as a
* result, with the remainder of the Futures as a sequence.
*
* #param fs a scala.collection.Seq
*/
def select[A](fs: Seq[Future[A]])(implicit ec: ExecutionContext):
Future[(Try[A], Seq[Future[A]])] = {
#scala.annotation.tailrec
def stripe(p: Promise[(Try[A], Seq[Future[A]])],
heads: Seq[Future[A]],
elem: Future[A],
tail: Seq[Future[A]]): Future[(Try[A], Seq[Future[A]])] = {
elem onComplete { res => if (!p.isCompleted) p.trySuccess((res, heads ++ tail)) }
if (tail.isEmpty) p.future
else stripe(p, heads :+ elem, tail.head, tail.tail)
}
if (fs.isEmpty) Future.failed(new IllegalArgumentException("empty future list!"))
else stripe(Promise(), fs.genericBuilder[Future[A]].result, fs.head, fs.tail)
}
}
I can then get what I need with
Enumerator.unfoldM(initialSeqOfFutureAs){ seqOfFutureAs =>
if (seqOfFutureAs.isEmpty) {
Future(None)
} else {
FutureUtil.select(seqOfFutureAs).map {
case (t, seqFuture) => t.toOption.map {
a => (seqFuture, a)
}
}
}
}
A better, shorter and I think more efficient answer is:
def toEnumerator(seqFutureX: Seq[Future[X]]) = new Enumerator[X] {
def apply[A](i: Iteratee[X, A]): Future[Iteratee[X, A]] = {
Future.sequence(seqFutureX).flatMap { seqX: Seq[X] =>
seqX.foldLeft(Future.successful(i)) {
case (i, x) => i.flatMap(_.feed(Input.El(x)))
}
}
}
}
I do realise that the question is a bit old already, but based on Santhosh's answer and the built-in Enumterator.enumerate() implementation I came up with the following:
def enumerateM[E](traversable: TraversableOnce[Future[E]])(implicit ec: ExecutionContext): Enumerator[E] = {
val it = traversable.toIterator
Enumerator.generateM {
if (it.hasNext) {
val next: Future[E] = it.next()
next map {
e => Some(e)
}
} else {
Future.successful[Option[E]] {
None
}
}
}
}
Note that unlike the first Viktor-select-based-solution this one preserves the order, but you can still start off all computations asynchronously before. So, for example, you can do the following:
// For lack of a better name
def mapEachM[E, NE](eventuallyList: Future[List[E]])(f: E => Future[NE])(implicit ec: ExecutionContext): Enumerator[NE] =
Enumerator.flatten(
eventuallyList map { list =>
enumerateM(list map f)
}
)
This latter method was in fact what I was looking for when I stumbled on this thread. Hope it helps someone! :)
You could construct one using the Java Executor Completeion Service (JavaDoc). The idea is to use create a sequence of new futures, each using ExecutorCompletionService.take() to wait for the next result. Each future will start, when the previous future has its result.
But please b e aware, that this might be not that efficient, because a lot of synchronisation is happening behind the scenes. It might be more efficient, to use some parallel map reduce for calculation (e.g. using Scala's ParSeq) and let the Enumerator wait for the complete result.
WARNING: Not compiled before answering
What about something like this:
def toEnumerator(seqFutureX: Seq[Future[X]]) = new Enumerator[X] {
def apply[A](i: Iteratee[X, A]): Future[Iteratee[X, A]] =
Future.fold(seqFutureX)(i){ case (i, x) => i.flatMap(_.feed(Input.El(x)))) }
}
Here is something I found handy,
def unfold[A,B](xs:Seq[A])(proc:A => Future[B])(implicit errorHandler:Throwable => B):Enumerator[B] = {
Enumerator.unfoldM (xs) { xs =>
if (xs.isEmpty) Future(None)
else proc(xs.head) map (b => Some(xs.tail,b)) recover {
case e => Some((xs.tail,errorHandler(e)))
}
}
}
def unfold[A,B](fxs:Future[Seq[A]])(proc:A => Future[B]) (implicit errorHandler1:Throwable => Seq[A], errorHandler:Throwable => B) :Enumerator[B] = {
(unfold(Seq(fxs))(fxs => fxs)(errorHandler1)).flatMap(unfold(_)(proc)(errorHandler))
}
def unfoldFutures[A,B](xsfxs:Seq[Future[Seq[A]]])(proc:A => Future[B]) (implicit errorHandler1:Throwable => Seq[A], errorHandler:Throwable => B) :Enumerator[B] = {
xsfxs.map(unfold(_)(proc)).reduceLeft((a,b) => a.andThen(b))
}
I would like to propose the use of a Broadcast
def seqToEnumerator[A](futuresA: Seq[Future[A]])(defaultValue: A, errorHandler: Throwable => A): Enumerator[A] ={
val (enumerator, channel) = Concurrent.broadcast[A]
futuresA.foreach(f => f.onComplete({
case Success(Some(a: A)) => channel.push(a)
case Success(None) => channel.push(defaultValue)
case Failure(exception) => channel.push(errorHandler(exception))
}))
enumerator
}
I added errorHandling and defaultValues but you can skip those by using onSuccess or onFailure, instead of onComplete