Lesson 6: Error handling
Scala for Java Developers
- Review of previous concepts
- Scala Try
- Regular try/catch
- Composability
- For-comprehensions
- Exercise
Recap
What is pattern matching and how does it work?
def teacher(lesson: Int) = lesson match {
case 1 => "Sonia"
case 2 => "Povilas"
case 3 => "Greg"
case 4 => "Sonia"
case 5 => "Greg"
case 6 => "Povilas"
case _ => "Can't predict the future"
}
sealed trait Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
def notication(msg: Notification): String = msg match {
case e: Email => e.title
case s: SMS => s.message
}
Pattern matching
What is a for comprehension?
val prices = List(100, 500, 450, 199)
// for-comprehension filtering
val highPrices = for (price <- prices if price > 200) yield price
// higher-order filter
val highPrices2 = prices.filter(price => price > 200)
val maybePrices = List(Some(100), Some(500), None, Some(199))
val maybeHighPrices =
for {
maybePrice <- maybePrices
price <- maybePrice
if price > 200
} yield price
val maybeHighPrices2 = maybePrices.flatMap(prices => prices.filter(price => price > 200))
Nested collections (flatMap)
Simple map
Error Handling in Scala
Traditional error handling
import java.net.URL
def parseURL(url: String): URL = new URL(url)
//traditional try/catch
def parseURL(url: String): URL =
try {
new URL(url)
} catch {
case e: MalformedURLException => println("Oh noes, pls try harder")
}
- Scala supports traditional Java style try/catch
-
Not as good when trying to compose multiple calls
Functional Error handling
scala.util.Try
One of more functional and composable ways to handle errors and failures
Try structure
sealed abstract class Try[T] {...}
final case class Success[T](value: T)
extends Try[T] {...}
final case class Failure[T](exception: Throwable)
extends Try[T] {...}
Implements higher-order methods
-
map
-
flatMap
-
filter (withFilter)
-
... and others
(spot the similarity to Option)
mapping
parseURL("http://hotels.com").map(_.getProtocol)
// results in Success("http")
import java.io.InputStream
def inputStreamForURL(url: String): Try[InputStream] = parseURL(url).flatMap { url =>
Try(url.openConnection()).flatMap(connection => Try(connection.getInputStream))
}
flatMapping
filtering
parseURL("http://hotels.com").filter(url => url.getProtocol == "ftp")
//results in Failure(java.util.NoSuchElementException)
import java.io.InputStream
def inputStreamForURL(url: String): Try[InputStream] = parseURL(url).flatMap { url =>
Try(url.openConnection()).flatMap(connection => Try(connection.getInputStream))
}
import java.io.InputStream
def inputStreamForURL2(url: String): Try[InputStream] = {
for {
parsedUrl <- parseURL(url)
connection <- Try(parsedUrl.openConnection())
inputStr <- Try(connection.getInputStream)
} yield inputStr
}
Translation into for-comprehensions
for-comprehension version
flatMap version
def parseURL(url: String): Try[URL] = Try(new URL(url))
val result = parseURL("http://www.hotels.com")
result match {
case Success(url) => println(url)
case Failure(e) => println(s"An error occurred: ${ex.getMessage}")
}
Consuming Try
parseURL("garbage") recover {
case e: MalformedURLException => "Please make sure to enter a valid URL"
case _ => "An unexpected error has occurred. We are so sorry!"
}
// returns Success(Please make sure to enter a valid URL)
Matching on a failure with recover
Pattern Matching
Exercise
cd path/to/scala-for-java-devs
git stash
git pull
git checkout lesson6
./sbt test
- 2 Exercises
- Aim to finish at least one from ForComprehensions
Scala For Java Devs 6
By Povilas Lape
Scala For Java Devs 6
Scala course lesson 6
- 117