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
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
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")
}
Not as good when trying to compose multiple calls
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
}
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
cd path/to/scala-for-java-devs
git stash
git pull
git checkout lesson6
./sbt test