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