L08. For expressions

A few motivational examples for using for expressions:

val l = List("this", "is", "a", "list", "of", "strings")
 
l.map(_.length)
 
l.map(_.length).filter(_ > 2)
 
// suppose we have another list of strings:
 
val l1 = List("is", "s", "th", "list", "str", "ings", "i", "t", "")
 
// suppose we have a dictionary (words which make sense in English)
val dictionary = l
 
/*
  We want to find ALL PAIRS of words from l1, which
  are valid English words
 */
 
// We start by constructing all pairs:
l1.map( str1=> l1.map(str2 => (str1,str2)))
  .reduce(_ ::: _)
  .filter( p => dictionary.contains(p._1 + p._2))
//  .foldRight(Nil:List[(String,String)])(_ ::: _)
 
// we have obtained: List[(String, String)]
 
 
 
/*
  This style of coding is very widespread, and for this reason,
  Scala has a special syntax for it.
 
  for expressions
 
 */
// l.map(_.length)
for (w <- dictionary) yield w.length
 
//l.map(_.length).filter(_ > 2)
for (w <- dictionary if w.length > 2) yield w.length
 
// alternative way to filter:
for ( sz <- (for (w <- dictionary) yield w.length) if sz > 2) yield sz
 
// solving the dictionary example:
 
for (w <- l1;
     wp <- l1 if dictionary.contains(w+wp))
  yield (w,wp)
 
// What else can we do with for expressions
 
val ls = List("a","b","c")
ls.reduce(_ + _)
ls.tail.foldRight(ls.head)(_ + _)
 
val lpp = List(List(1,2,3),List(4,5,6))
for (x <- lpp;
     y <- x)
        yield 2*y
 
// WHAT TYPE?
// it must be a List[Int]
 
for (x <- lpp)
  yield
    for (y <- x)
      yield 2*y
 
 
List(1,2,3).zip(List(4,5,6))
 
(0.to(10)).toList

Nested for expressions in he matrix case study:

object Matrix {
 
  // these are type aliases
  // LIKE typedef
 
  type Line = List[Int]
  type Matrix = List[Line]
 
 
  val m = List(List(1,2,3), List(4,5,6), List(7,8,9))
 
  // display a matrix
  /*
  List(List(1,2,3), List(4,5,6), List(7,8,9)) :: List[List[Int]]
  List(List("1","2","3"), List("4","5","6"), List("7","8","9")) :: List[List[String]]
  List("1 2 3\n", "4 5 6\n", "7 8 9\n") :: List[String]
  "1 2 3\n4 5 6\n7 8 9\n" :: String
   */
 
  def show (m: Matrix): String = {
    m.map(line => line.foldRight("\n")(_.toString+" "+_))
      .reduce(_ + _)
  }
 
 
  /*
    def show (m: Matrix): String = {
    m.map((line: List[Int]) => line.map(_.toString))
      .map((line: List[String]) => line.foldRight("\n")(_ + _) )
      .reduce(_ + _)
  }
   */
 
  val x = List(1,2,3)
  val y = List(1,1,1)
 
  def mult(c: Int, m: Matrix): Matrix =
    //m.map(_.map(_*c))
    for (l <- m)
      yield
        for (v <- l)
          yield c*v
 
  //
  def scalar(x:List[Int], y: List[Int]): Int = {
    //(for ((x,y) <- x.zip(y)) yield x*y).sum
    // alternative based on indices instead of values
    (for (i <- 0.until(x.length)) yield x(i)*y(i)).sum
  }
 
  // m :: List[List[Int]]
  // the first line of transpose(m) = the first column
  m.map(_.head)
 
  def transpose (m: Matrix): Matrix =
    m match {
      case Nil :: _ => Nil
      case _ => m.map(_.head) :: transpose(m.map(_.tail))
    }
 
 
  def mult(m1: Matrix, m2: Matrix): Matrix = {
    //m1.map(l => (transpose(m2)).map (c => scalar(l,c)))
    val snd = transpose(m2)
    for (l <- m1)
      yield
        for (c <- snd)
          yield scalar(l,c)
  }
 
 
  def main(args: Array[String]) = {
 
    println(show(m))
    /* Important remark!!
    * NESTED FOR EXPRESSIONS */
 
 
 
  }
 
 
}