math4tots math4tots - 1 month ago 15
Scala Question

Scala `map` but exit early on `Failure`

If I have a

Seq
, I can
map
over it.

val ss = Seq("1", "2", "3")
println(ss.map(s => s.toInt)) // List(1, 2, 3)


But sometimes, the function that you pass to
map
can fail.

val ss = Seq("1", "2", "c")
println(ss.map(s => try { Success(s.toInt) } catch { case e: Throwable => Failure(e) })) // List(Success(1), Success(2), Failure(java.lang.NumberFormatException: For input string: "c"))


This last one will return a
Seq[Try[Int]]
. What I really want though is a
Try[Seq[Int]]
, where if any one of the mapping is a
Failure
, it stops the iteration and returns the
Failure
instead. If there is no error, I want it to just return all the converted elements, unpacked from the
Try
.

What is the idiomatic Scala way to do this?

m-z m-z
Answer

You may be overthinking this. The anonymous function in your map is essentially the same as Try.apply. If you want to end up with Try[Seq[Int]] then you can wrap the Seq in Try.apply and map within:

scala> val ss = Try(Seq("1", "2", "c").map(_.toInt))
ss: scala.util.Try[Seq[Int]] = Failure(java.lang.NumberFormatException: For input string: "c")

If any of the toInts fails, it will throw an exception and stop executing, and become a Failure.

Comments