"For comprehension" is a another syntax to use map, flatMap and withFilter (or filter) methods.
yield keyword is used to aggregate values in the resulting structure.
This composition can be used on any type implementing this methods, like List, Option, Future...
Install jad:
brew install homebrew/binary/jad
-
Compile the code:
scalac -d out Forcomptran.scala -
To see the decompiled code, run (for example, Case1):
jad -lnc -p -t 2 -v ./out/Case1\$.class
case class Book(author: String, title: String)for {
book <- books if book.author startsWith "Ivan"
} yield book.titleis the same as:
books.withFilter(book => book.author startsWith "Ivan")
.map(book => book.title)case class Book(author: String, title: String)for { book <- books
author = book.author.replaceAll("\\s+", "_").toLowerCase
if author startsWith "ivan"
} yield s"$author: ${book.title}"is the same as:
books
.map(book => (book, book.author.replaceAll("\\s+", "_").toLowerCase)) // Tuple2(book, author)
.withFilter(_._2 startsWith "ivan")
.map { case (book, author) => s"$author: ${book.title}" }case class Book(authors: List[String], title: String)for {
book <- books
author <- book.authors if author contains "er"
} yield book.titleis the same as:
books.flatMap(book =>
book.authors.withFilter(author => author contains "er")
.map(author => book.title))val optA : Option[String] = Some("a value")
val optB : Option[String] = Some("b value")I want an option tuple : Option[(String, String) composing this two options, i.e. Some(("a value","b value")) :
for {
a <- optA
b <- optB
} yield (a,b)is the same as:
optA.flatMap(a =>
optB.map(b =>
(a, b)))You can also filter options with if / withFilter:
for {
/* 1 */ a <- optA
/* 2 */ if a startsWith "a"
/* 3 */ b <- optB
} yield (a,b)Or:
/* 2 */ optA.withFilter(a => a startsWith "a")
/* 1 */ .flatMap(a =>
/* 3 */ optB.map(b =>
(a, b)))If you change "a" to "c" in the condition, the resulting value will be None instead of Some(("a value","b value")).
You can mix options and list types in map/flatMap (Option can be seen as a simple collection) :
val optNumbers = List(Some(1), Some(2), None, Some(3))We want to remove empty values and increment other values : List(2, 3, 4) :
for {
optNumber <- optNumbers
value <- optNumber
} yield value + 1is the same as:
optNumbers.flatMap(optNumber =>
optNumber.map(value =>
value + 1))