What triggers Try argument to be evaluated - scala

I was tinkering with Try, per this:
val files = Stream("a.txt", "b.txt", "c.txt")
files
.map(s => Try(Source.fromFile(s)))
.flatMap(t => t match {
case Failure(x) =>
Console.err.println(s"Failure: x.getMessage")
Stream.Empty
case Success(s) => Stream(s)
})
.flatMap(t => t.getLines.toStream)
.foreach(println)
and while it works, exactly as I hoped/intended, I was left with an uneasy feeling that I could not identify exactly how the "Source.fromFile(s)" part actually gets evaluated. the argument to the Try.apply method is documented as a by-name parameter, so clearly something must force evaluation of that.
But, it seems to me that the very next operation would be the "t match" part, and that's looking at the type of object that the Try.apply created, and that can't work if the object hasn't been created, and it can't be created without evaluating the argument to apply. In which case, I don't see any point the argument being in the first place.
Or, perhaps there's something intrinsically lazy about the behavior of case classes? Or maybe I'm just missing something obvious.
Would someone mind clarifying this for me?

The part you are missing is that the argument to Try has to be by-name so that exceptions thrown by that computation can be caught and reified as Failures. Otherwise the argument would be evaluated before Try has had a chance to catch anything which would defeat the purpose. You can even look at the source code of Try.apply which is very simple. It immediately forces its argument:
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}

Related

java.io.Serializable to Seq Scala

I have a case match statement that provides the following output. I'm trying to convert this into a sequence instead. Can you please help me with this?
java.io.Serializable = List(TableInfo(X,XX,List(aa#aa.com, bb#bb.com)),
TableInfo(Y,YY,List(aa#aa.com, bb#bb.com)))
[Code]:
scala.util.Either[Exception,List[TableInfo]] =
Right(List(TableInfo(X,XX,List(aa#aa.com, bb#bb.com)),
TableInfo(Y,YY,List(aa#aa.com, bb#bb.com))))
result match {
case Left(s) => s
case Right(i) => i
}
Complete Code: https://scastie.scala-lang.org/HT8wmYtsRF6DwzEkJYeygA
Your code doesn't throw any exceptions right now. Based on the comments, it sounds like your intention is to extract a Right or throw whatever's on the Left. In that case, all you're missing is the throw keyword.
result match {
case Left(s) => throw s
case Right(i) => i
}
throw breaks the normal flow of control, so it returns Nothing, which is the unique subtype of all types in Scala. Thus, the common types of Nothing and whatever s is, is simply the type of s.

Scala, how to not use None

I have a bit of code that I am checking with Scala Scapegoat. I am not sure how to refactor this code the way it wants.
def strToDouble(valueParam: Option[String]): Option[java.lang.Double] = {
valueParam.map(value => {
Try {
Double.box(value.toDouble)
}.recoverWith({
case e: NumberFormatException => {
val logger = LoggerFactory.getLogger(getClass.getName)
logger.warn("error parsing string to double", e)
return None
}
}).getOrElse(null)
})
}
Scapegoat is complaining about my use of return and the getOrElse(null). Unfortunately in this situation I can't figure out how to do what I want:
convert the string to double, returning Option[Double]
log an error if there is a parsing error
return None in the case of parsing error
any ideas?
In general in Scala, you never need to use return, and it has some surprising semantics so it's generally advised to never use return.
Instead of return, the result of a block expression (such as the body of a function) is the result of the last expression evaluated in the block.
I would write your code along these lines
valueParam.flatMap { value =>
val attempt =
Try {
Double.box(value.toDouble)
}
attempt.recoverWith {
case e: NumberFormatException =>
val logger = LoggerFactory.getLogger(getClass.getName)
logger.warn("error parsing string to double", e)
attempt
}.toOption
}
The first key difference is that since we're transforming an Option into another Option, and might sometimes turn a Some into a None (e.g. Some("hello")), flatMap is called for.
Saving the Try[Double] in a local val enables us to get around there not being a foreach equivalent on a failed Try, thus the recoverWith which results in the same Try after side-effecting.
At the end, we convert the Try into an Option with toOption.
null is generally never used in Scala, with Option preferred (and an Option which could be null is especially verboten, as it's virtually guaranteed to blow up). If you have an Option[java.lang.Double] and need a possibly null java.lang.Double in order to work with a Java API, the orNull method on an Option is probably the most idiomatic thing to use.
I'm fairly sure that scala.Double is, on the JVM, a compiler-synthesized alias for java.lang.Double, so Double.box might not be needed.
Everything that #Levi said. I just have a preference for fold() in place of recooverWith().
import scala.util.Try
def strToDouble(valueParam: Option[String]): Option[Double] =
valueParam.flatMap { value =>
Try(value.toDouble).fold({
case e:NumberFormatException =>
LoggerFactory.getLogger(getClass.getName)
.warn("error parsing string to double", e)
None
}, Some(_))
}

Future.successful(Failure(Exception)) vs just Future.failed()

I am trying to understand the difference why someone will use Future.successful(Failure(ServiceException("error"))) rather than Future.failed(ex) in Scala.
Future.successful(
Failure(
ServiceException(ErrorTypes.Validation, "Value should not be more than 30")
)
)
It's hard to say why the author did what they did, I can guess a couple of reasons:
They are not aware that you can Future.fail to return a failed future. This may happen because the signature of future doesn't convey the failure path explicitly in the type. When you see Future[A], you may think this computation must succeed in the future
They wanted to be explicit about failure. When I declare Future[Try[A]], I am forcing the caller to deal with the fact that can't directly access A, but have to "jump another hop" to get inside for A. Although this is delicate, as one can easily write:
val f: Future[Try[String]] = ???
f.map(_.map(str => // stuff with string))
But perhaps the signature forces the caller to realize the possibility of failure. Although Try is pretty limiting in it's expressiveness as well, as it can only return a Throwable on the failure path. I find Future[Either[E, A]] to be more expressive in that regards, which allows you to build your own failure hierarchy and encode it in the type.
There is an ever lasting debate regarding unary functor IO types (Future[A]) vs bi-functor IO types (IO[E, A], i.e. ZIO). I am in favor of bi-functor and have been using it solely recently, and I find it to be really time-saving when I don't have to dig into the implementation to understand the possible failures of a computation.
I would like to add on top of the great answer by #YuvalItzchakov, that writing code as in your question complicates the code and makes it unnatural. For example, let's assume that this future normally an Int, something like:
val succeeded = true // or any other computation
val future = if(succeeded) {
Future.successful(42)
} else {
Future.successful(Failure(new Exception("some failure text")))
}
Then first, the type of future is Future[Any], because Any is the lowest common root of Int and Failure, which is not convenient. But then, to map on it, you need to do:
future.map {
case i: Int =>
println(i)
case Failure(ex) =>
println(ex.getMessage)
} recover {
case NonFatal(ex) =>
println(s"recover ${ex.getMessage}")
}
Which feels weird to pattern match Int and Failure in the same match case. If you do want to pattern match Success and Failure, we had to do:
val succeeded = true // or any other computation
val future = if(succeeded) {
Future.successful(Success(42))
} else {
Future.successful(Failure(new Exception("some failure text")))
}
But that is already pretty clear as redundancy, right? No one will call Future.successful(Success(42)). So I think that it is pretty clear to use Future.failed(new Exception("some failure text")).

Returning Future[Int] from Future[Option[Int]] with support of Failing the future

I have the below block of code. My intent is to do some processing with the method params and return Future[Int] or fail the Future. I want to fail the Future if my argument to method inside the Future is of type None. I have the below code. I wonder if there is a much more concise and functional way to achieve the same.
def testoption(myFutOptInt: Future[Option[Int]]) = {
myFutOptInt.map { myOptInt =>
myOptInt match {
case None => throw new BadRequestException("Oh no.....") //Future.failed(BadRequestException(""))
case Some(myInt) => myInt + 45
}
} recoverWith {
case e:Exception => Future.failed(e)
}
}
I am not liking the part that I have to do a match, wondering if there is a way to do a map or something better and still achieve it. If I do getOrElse I guess I won't be able to write the business logic if the value is not None? So getOrElse is not possible either I think?
The other thing I do not like about this code is that I am throwing an exception and then I have to do recoverWith to fail the Future.
I can enhance the above code how?
If you need specifically BadRequestException, this is enough:
def testoption(myFutOptInt: Future[Option[Int]]) =
myFutOptInt.map {
case None => throw new BadRequestException("Oh no.....")
case Some(myInt) => myInt + 45
}
And if you don't care about particular error type, you can cut it even more:
def testoption(myFutOptInt: Future[Option[Int]]) = myFutOptInt.map(_.get + 45)
This will give you java.util.NoSuchElementException: None.get if there's no value
recoverWith is absolutely redundant b/c if an exception is thrown inside a map, whole operation results in a failed Future. This is true for most, if not all, Future methods.
For match, you can avoid it using opt.fold(throw ...)(...) or .map(...).getOrElse(throw ...), but I'd argue those options are less readable. I suggest just using pattern-matching function definition to reduce extra code

Scala Multiple Future wrapped in Try

Suppose I have many akka services which all return a case class of type AbcDto wrapped in a Try.
So I call all these services using map and get back a List[Future[Any]].
Now I use Future.sequence to convert this to Future[List[Any]].
How do I unwrap my final list of results? I want to process them only when all of them are a Success and even if one fails I want to throw an error.
I tried mapping Future[List[Any]] as:
val a: List[Future[Any]]
a.map {
case r: List[Success[AbcDto]] => println("hello")
}
But this gives error:
case r: List[Try[AbcDto]]. At this point its giving error: non-variable type argument scala.util.Try[AbcDto] in type pattern List[scala.util.Try[AbcDto]] (the underlying of List[scala.util.Try[AbcDto]])
since all akka services return AbcDtowrapped in a Try the proper type of val a should be List[Future[Try[AbcDto]]]. Now the desired result can be achieved by a combination of Future.sequence and flatMap operation to check for any Failures in the service as shown below.
val a: List[Future[Try[AbcDto]]] = ...
val result: Future[List[AbcDto]] = Future.sequence(a) flatMap {
case r: List[Try[AbcDto]] #unchecked if r.find(!_.isSuccess).isDefined => Future.failed(new RuntimeException("not all results are successful"))
case r => Future.successful(r.collect({ case Success(x) => x}))
}
Future[A] and Try[A] in the actor context are so similar that I see no point to return Try[A] from those actors. You just return A in case of success, which will be Future[A] on asking side, a List of which you can sequence and get Future[List[A]], which, in case of a single failure, will contain the first encountered exception. It seems to be exactly what you're asking for.
To communicate failure from an actor to the asker, you should send akka.actor.Status.Failure with the relevant instance of Throwable.
P.S. regarding comment that using try-catch is non-idiomatic Scala. It actually is. Here's how Try creation is implemented:
object Try {
/** Constructs a `Try` using the by-name parameter. This
* method will ensure any non-fatal exception is caught and a
* `Failure` object is returned.
*/
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
}
As you can see, it uses try-catch inside. If Scala standard library authors are fine with that, so should be you. :)
If I understand you correctly (the types in your question are a bit confusing),
You start with a val responseFutures: List[Future[Any]] and after conversion you have a val responsesFuture: Future[List[Any]]. rogue-ones answer is correct, but it could use some clarification:
Your compiler error is caused by the fact that Success is not a class, but an extractor object with unapply for Try. Therefore you cannot use in in type extraction this way.
So something like case r: List[Try[AbcDto]] if r.forall(_.isSuccess) => println("hello") should compile. However, as AbcDto is erased, you will get a compiler warning about erasure. Thus the #unchecked.
UPDATE
Type erasure means, the compiler cannot check type argument type in pattern matches at compile time. In your case, all the compile knows of your input type is Future[List[Try[Any]]].
So
future.map {
case _: List[Try[AbcDto]] => ???
}
will cause a compiler warning because the compiler only sees.
future.map {
case _: List[Try[_]] => ???
}
The #unchecked annotation just suppresses the corresponding compiler warning.
In the end with the pattern match above you just cast whatever is coming in to Try[AbcDto] without any compile time type safety.