Scala Learning (2): map, flatMap, filter and For expressions, scalaflatmap
This article describes the relationships among the three most common operations map, flatMap, filter, and For expressions in Collections.
List Implementation of three methods
Map implementation in List:
abstract class List[+T] { def map[U](f: T => U): List[U] = this match { case x :: xs => f(x) :: xs.map(f) case Nil => Nil }}
Implementation of flatMap in List:
abstract class List[+T] { def flatMap[U](f: T => List[U]): List[U] = this match { case x :: xs => f(x) ++ xs.flatMap(f) case Nil => Nil }}
Filter Implementation in List:
abstract class List[+T] { def filter(p: T => Boolean): List[T] = this match { case x :: xs => if (p(x)) x :: xs.filter(p) else xs.filter(p) case Nil => Nil }}
For expression
The following logic can be expressed in:
(1 until n) flatMap (i => (1 until i) filter (j => isPrime(i + j)) map (j => (i, j)))
for { i <- 1 until n j <- 1 until i if isPrime(i + j)} yield (i, j)
For and map
for (x <- e1) yield e2// translated toe1.map(x => e2)
For and filter
for (x <- e1 if f; s) yield e2// translated tofor (x <- e1.withFilter(x => f); s) yield e2
For and flatMap
for (x <- e1; y <- e2; s) yield e3// translated toe1.flatMap(x => for (y <- e2; s) yield e3)
For and Pattern Matching
Combined with the example in the previous article (expressed in JSON), we used for map and filter operations:
val data: List[JSON] = ...for { JObj(bindings) <- data JSeq(phones) = bindings("phoneNumbers") JObj(phone) <- phones JStr(digits) = phone("number") if digits startsWith "212"} yield (bindings("firstName"), bindings("lastName"))
The general translation process of Pattern Matching in:
pat <- expr// tox <- expr withFilter { case pat => true case _ => false } map { case pat => x }
Exercise
for { x <- 2 to N y <- 2 to x if (x % y == 0)} yield (x, y)
It can be translated:
(2 to N) flatMap (x => (2 to x) withFilter (y => x % y == 0) map (y => (x, y)))
Refer to self-Principles of Reactive Programming
Full Text :)