====== 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 */ } }