Sunday, January 1, 2012

Learning Scala : Reading the exotic and essential List API scaladoc 11

Authored by Win Myo Htet



Our current logical grouping this time includes flatMap, flatten, map and mapConserve.
def flatMap [B] (f: (A) ⇒ GenTraversableOnce[B]): List[B]
[use case] Builds a new collection by applying a function to all elements of this list and concatenating the results.
def flatMap [B, That] (f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
Builds a new collection by applying a function to all elements of this list and concatenating the results.
def flatten [B] : List[B]
[use case] Converts this list of traversable collections into a list in which all element collections are concatenated.
def flatten [B] (implicit asTraversable: (A) ⇒ TraversableOnce[B]): Traversable[B]
Converts this list of traversable collections into a list in which all element collections are concatenated.
def map [B] (f: (A) ⇒ B): List[B]
[use case] Builds a new collection by applying a function to all elements of this list.
def map [B, That] (f: (A) ⇒ B)(implicit bf: CanBuildFrom[List[A], B, That]): That
Builds a new collection by applying a function to all elements of this list.
def mapConserve[A <: AnyRef](xs: List[A])(f: A => A): List[A]
[use case] Builds a new list by applying a function to all elements of this list.
def mapConserve [B >: A <: AnyRef] (f: (A) ⇒ B): List[B]
Builds a new list by applying a function to all elements of this list.

We create some vals. The first one is List[Option[Int]] with None included, then standard List of Int and List of Lists. We use flatten to get the List with value, which is unwrapped from Option. (the new List will not have element represented for None.) flatten can also be used to unwrapped elements from inner Lists of a List, which has Lists as elements.
scala>  val optionl= None::(for(i <- 1 to 9) yield Option(i)).toList
optionl: List[Option[Int]] = List(None, Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9))

scala> val list = (for (i <- 1 to 9) yield i).toList
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val lol = optionl::list::List(11,12,13,14,15,16)::Nil
lol: List[List[Any]] = List(List(None, Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9)), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(11, 12, 13, 14, 15, 16))

scala> for( l <- lol) println(l)
List(None, Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9))
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
List(11, 12, 13, 14, 15, 16)

scala> optionl flatten
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> lol flatten
res2: List[Any] = List(None, Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16)

We will continue using vals from above. For simplicity sake, we will say that flatMap also operates on List of Lists. Using a predefined function identity, which simply return the same element, from predefwe can use flatMap to be like flatten. However map operates on non List elements. We combine the functions to get the simple List[Int].
scala> lol flatMap identity
res3: List[Any] = List(None, Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16)

scala> lol flatMap identity map{case Some(x) => x; case None => 0;case x => x}
res4: List[Any] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16)

scala> val r=lol flatMap identity map{case Some(x) => x; case None => 0;case x => x} map {case x:Int => x}
r: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16)

mapConserve is similar to map but the requirement is that mapConserve can only be operated on subtype of AnyRef. mapConserve also has performance advantage on map.
scala> val mcl=List("This","is","an","example","to","use","mapConverse")
mcl: List[java.lang.String] = List(This, is, an, example, to, use, mapConverse)

scala> mcl map (x => x.toUpperCase)
res5: List[java.lang.String] = List(THIS, IS, AN, EXAMPLE, TO, USE, MAPCONVERSE)

scala>  mcl mapConserve (x => x.toUpperCase)
res6: List[java.lang.String] = List(THIS, IS, AN, EXAMPLE, TO, USE, MAPCONVERSE)

scala> val optionr = r map {x => Option(x) }
optionr: List[Option[Int]] = List(Some(0), Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(11), Some(12), Some(13), Some(14), Some(15), Some(16))

scala> optionr mapConserve { x => Option(x.get * x.get)}
res7: List[Option[Int]] = List(Some(0), Some(1), Some(4), Some(9), Some(16), Some(25), Some(36), Some(49), Some(64), Some(81), Some(1), Some(4), Some(9), Some(16), Some(25), Some(36), Some(49), Some(64), Some(81), Some(121), Some(144), Some(169), Some(196), Some(225), Some(256))

If you would like to learn how and where some of these functions are deployed, you are in luck. You can see their usage in my first blog series, Chewy code : scala TicTacToe. Since we have covered fold and for series before, we will be addressing functions starting with genericBuilder.


Authored by Win Myo Htet

No comments:

Post a Comment