Skip to content

Instantly share code, notes, and snippets.

@jehrhardt
Created September 8, 2015 07:09
Show Gist options
  • Save jehrhardt/83a6c347b9e9727114ab to your computer and use it in GitHub Desktop.
Save jehrhardt/83a6c347b9e9727114ab to your computer and use it in GitHub Desktop.

Errors

Dealing with errors in Scala.

for comprehension

Simple foreach

type Blog = Int
type BlogArticle = Int

def findArticles(blog: Blog): Seq[BlogArticle] = if (blog < 2) Seq() else Range(1, blog)

val blogs: Seq[Blog] = Seq(1, 2, 3)

Seq(1, 2, 3).foreach(blog => findArticles(blog))
Seq(1, 2, 3).foreach(blog => findArticles(blog).foreach(identity))

Can be written with for comprehension

for(blog <- blogs) {
  findArticles(i)
}

for {
  blog <- blogs
  article <- findArticles(blog)
} {
  identity(article)
}

Similar with map and flatMap

blogs.flatMap(blog => findArticles(blog).map(identity))

for {
  blog <- blogs
  article <- findArticles(blog)
} yield {
  identity(article)
}

Even filtering possible

blogs.flatMap(blog => findArticles(blog).withFilter(_ == 1).map(identity))

for {
  blog <- blogs
  article <- findArticles(blog)
  if article == 1
} yield {
  identity(article)
}

assert and require

def byId(id: Int): Blog = {
  assert(id > 0, "i must be greater than 1")
  id
}

byId(0)  AssertionError

require with optional message is also possible

def byId(id: Int): Blog = {
  require(id > 0, "i must be greater than 1")
  id
}

byId(0)  IllegalArgumentException

require's message is call by name!

Exceptions

There are exceptions in Scala and they are typically case classes

case class BlogNotFoundException(message: String) extends Exception(message)

def byId(id: Int): Blog = {
  require(id > 0, "i must be greater than 1")

  if(id == 1) {
    id
  } else {
    throw BlogNotFoundException(s"Could not find blog with ID $id")
  }
}

byId(1)

try {
  byId(2)
} catch {
  case BlogNotFoundException(message) => message
}

Try catch is an expression with return value

val blog = {
  try {
    byId(2)
  } catch {
    case BlogNotFoundException(message) => message
  }
}

Either

Either can be used for explicit types

val blog: Either[String, Blog] = {
  try {
    Right(byId(2))
  } catch {
    case BlogNotFoundException(message) => Left(message)
  }
}

blog match {
  case Right(blog) => blog
  case Left(message) => 0
}

By convention is left the error and right the success!

Either right or left to make it work like collections

blog.right.map(i => i * 10)  map will not be executed, since it is left
blog.left.map(i => i * 10)  map will be executed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment