1 // Scala Lecture 5  | 
     1 // Scala Lecture 5  | 
     2 //=================  | 
     2 //=================  | 
     3   | 
     3   | 
     4   | 
     4   | 
     5   | 
         | 
     6 // Laziness with style  | 
     5 // Laziness with style  | 
     7 //=====================  | 
     6 //=====================  | 
     8   | 
     7   | 
     9 // The concept of lazy evaluation doesn’t really   | 
     8 // The concept of lazy evaluation doesn’t really   | 
    10 // exist in non-functional languages. C-like languages  | 
     9 // exist in non-functional languages. C-like languages  | 
    11 // are strict. To see the difference, consider  | 
    10 // are (sort of) strict. To see the difference, consider  | 
    12   | 
    11   | 
    13 def square(x: Int) = x * x  | 
    12 def square(x: Int) = x * x  | 
    14   | 
    13   | 
    15 square(42 + 8)  | 
    14 square(42 + 8)  | 
    16   | 
    15   | 
    17 // This is called "strict evaluation".  | 
    16 // This is called "strict evaluation".  | 
    18   | 
    17   | 
    19 // In contrast, say we have a pretty expensive operation:  | 
    18 // On the contrary, say we have a pretty expensive operation:  | 
    20   | 
    19   | 
    21 def peop(n: BigInt): Boolean = peop(n + 1)   | 
    20 def peop(n: BigInt): Boolean = peop(n + 1)   | 
    22   | 
    21   | 
    23 val a = "foo"  | 
    22 val a = "foo"  | 
    24 val b = "bar"  | 
    23 val b = "foo"  | 
    25   | 
    24   | 
    26 if (a == b || peop(0)) println("true") else println("false") | 
    25 if (a == b || peop(0)) println("true") else println("false") | 
    27   | 
    26   | 
    28 // This is called "lazy evaluation":  | 
    27 // This is called "lazy evaluation":  | 
    29 // you delay compuation until it is really   | 
    28 // you delay compuation until it is really   | 
    46   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))  | 
    45   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))  | 
    47   | 
    46   | 
    48 val primes = generatePrimes(LazyList.from(2))  | 
    47 val primes = generatePrimes(LazyList.from(2))  | 
    49   | 
    48   | 
    50 // the first 10 primes  | 
    49 // the first 10 primes  | 
    51 primes.take(10).toList  | 
    50 primes.take(100).toList  | 
    52   | 
    51   | 
    53 time_needed(1, primes.filter(_ > 100).take(3000).toList)  | 
    52 time_needed(1, primes.filter(_ > 100).take(3000).toList)  | 
    54 time_needed(1, primes.filter(_ > 100).take(3000).toList)  | 
    53 time_needed(1, primes.filter(_ > 100).take(3000).toList)  | 
    55   | 
    54   | 
    56 // A Stream (LazyList) of successive numbers:  | 
    55 // A Stream (LazyList) of successive numbers:  | 
   111   def ~ (r: Rexp) = SEQ(s, r)  | 
   110   def ~ (r: Rexp) = SEQ(s, r)  | 
   112   def ~ (r: String) = SEQ(s, r)  | 
   111   def ~ (r: String) = SEQ(s, r)  | 
   113 }  | 
   112 }  | 
   114   | 
   113   | 
   115   | 
   114   | 
   116 def depth(r: Rexp) : Int = r match { | 
   115   | 
   117   case ZERO => 0  | 
         | 
   118   case ONE => 0  | 
         | 
   119   case CHAR(_) => 0  | 
         | 
   120   case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1  | 
         | 
   121   case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1   | 
         | 
   122   case STAR(r1) => depth(r1) + 1  | 
         | 
   123 }  | 
         | 
   124   | 
   116   | 
   125 //example regular expressions  | 
   117 //example regular expressions  | 
   126 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"  | 
   118 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"  | 
   127 val sign = "+" | "-" | ""  | 
   119 val sign = "+" | "-" | ""  | 
   128 val number = sign ~ digit ~ digit.%   | 
   120 val number = sign ~ digit ~ digit.%   | 
   155                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::  | 
   147                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::  | 
   156                 (for (r1 <- rs) yield STAR(r1)) )  | 
   148                 (for (r1 <- rs) yield STAR(r1)) )  | 
   157   | 
   149   | 
   158   | 
   150   | 
   159 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force | 
   151 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force | 
   160 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000) | 
   152 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000).force | 
         | 
   153   | 
         | 
   154   | 
         | 
   155 def depth(r: Rexp) : Int = r match { | 
         | 
   156   case ZERO => 0  | 
         | 
   157   case ONE => 0  | 
         | 
   158   case CHAR(_) => 0  | 
         | 
   159   case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1  | 
         | 
   160   case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1   | 
         | 
   161   case STAR(r1) => depth(r1) + 1  | 
         | 
   162 }  | 
   161   | 
   163   | 
   162   | 
   164   | 
   163 val is =   | 
   165 val is =   | 
   164   (enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))) | 
   166   (enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))) | 
   165     .dropWhile(depth(_) < 3)  | 
   167     .dropWhile(depth(_) < 3)  | 
   174 // length and so on for every type of lists.  | 
   176 // length and so on for every type of lists.  | 
   175   | 
   177   | 
   176   | 
   178   | 
   177 def length_string_list(lst: List[String]): Int = lst match { | 
   179 def length_string_list(lst: List[String]): Int = lst match { | 
   178   case Nil => 0  | 
   180   case Nil => 0  | 
   179   case x::xs => 1 + length_string_list(xs)  | 
   181   case _::xs => 1 + length_string_list(xs)  | 
   180 }  | 
   182 }  | 
   181   | 
   183   | 
   182 def length_int_list(lst: List[Int]): Int = lst match { | 
   184 def length_int_list(lst: List[Int]): Int = lst match { | 
   183   case Nil => 0  | 
   185   case Nil => 0  | 
   184   case x::xs => 1 + length_int_list(xs)  | 
   186   case x::xs => 1 + length_int_list(xs)  | 
   185 }  | 
   187 }  | 
   186   | 
   188   | 
   187 length_string_list(List("1", "2", "3", "4")) | 
   189 length_string_list(List("1", "2", "3", "4")) | 
   188 length_int_list(List(1, 2, 3, 4))  | 
   190 length_string_list(List(1, 2, 3, 4))  | 
   189   | 
   191   | 
   190 // you can make the function parametric in type(s)  | 
   192 // you can make the function parametric in type(s)  | 
   191   | 
   193   | 
   192 def length[A](lst: List[A]): Int = lst match { | 
   194 def length[A](lst: List[A]): Int = lst match { | 
   193   case Nil => 0  | 
   195   case Nil => 0  | 
   194   case x::xs => 1 + length(xs)  | 
   196   case x::xs => 1 + length(xs)  | 
   195 }  | 
   197 }  | 
   196 length(List("1", "2", "3", "4")) | 
   198 length[String](List("1", "2", "3", "4")) | 
   197 length(List(1, 2, 3, 4))  | 
   199 length(List(1, 2, 3, 4))  | 
   198   | 
   200   | 
   199   | 
   201   | 
   200 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { | 
   202 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { | 
   201   case Nil => Nil  | 
   203   case Nil => Nil  | 
   218                      f: B => C,   | 
   220                      f: B => C,   | 
   219                      acc: List[C] = Nil): List[B] = xs match { | 
   221                      acc: List[C] = Nil): List[B] = xs match { | 
   220   case Nil => Nil  | 
   222   case Nil => Nil  | 
   221   case x::xs => { | 
   223   case x::xs => { | 
   222     val res = f(x)  | 
   224     val res = f(x)  | 
   223     if (acc.contains(res)) distinctBy(xs, f, acc)    | 
   225     if (acc.contains(res) distinctBy(xs, f, acc)    | 
   224     else x::distinctBy(xs, f, res::acc)  | 
   226     else x::distinctBy(xs, f, res::acc)  | 
   225   }  | 
   227   }  | 
   226 }   | 
   228 }   | 
   227   | 
   229   | 
   228 val cs = List('A', 'b', 'a', 'c', 'B', 'D', 'd') | 
   230 val cs = List('A', 'b', 'a', 'c', 'B', 'D', 'd') | 
   240   | 
   242   | 
   241 val x = id(322)          // Int  | 
   243 val x = id(322)          // Int  | 
   242 val y = id("hey")        // String | 
   244 val y = id("hey")        // String | 
   243 val z = id(Set(1,2,3,4)) // Set[Int]  | 
   245 val z = id(Set(1,2,3,4)) // Set[Int]  | 
   244   | 
   246   | 
   245   | 
   247 id[+A, -B]  | 
   246   | 
   248   | 
   247 // The type variable concept in Scala can get really complicated.  | 
   249 // The type variable concept in Scala can get really complicated.  | 
   248 //  | 
   250 //  | 
   249 // - variance (OO)  | 
   251 // - variance (OO)  | 
   250 // - bounds (subtyping)  | 
   252 // - bounds (subtyping)  | 
   264   | 
   266   | 
   265 var arr = Array[Int]()  | 
   267 var arr = Array[Int]()  | 
   266 arr(0) = "Hello World"  | 
   268 arr(0) = "Hello World"  | 
   267   | 
   269   | 
   268   | 
   270   | 
   269   | 
         | 
   270 // (Immutable)  | 
   271 // (Immutable)  | 
   271 // Object Oriented Programming in Scala  | 
   272 // Object Oriented Programming in Scala  | 
   272 //  | 
   273 //  | 
   273 // =====================================  | 
   274 // =====================================  | 
   274   | 
   275   | 
   275 abstract class Animal  | 
   276   | 
         | 
   277 abstract class Animal   | 
   276 case class Bird(name: String) extends Animal { | 
   278 case class Bird(name: String) extends Animal { | 
   277    override def toString = name  | 
   279    override def toString = name  | 
   278 }  | 
   280 }  | 
   279 case class Mammal(name: String) extends Animal  | 
   281 case class Mammal(name: String) extends Animal  | 
   280 case class Reptile(name: String) extends Animal  | 
   282 case class Reptile(name: String) extends Animal  | 
   546 val eight = 0.8  | 
   546 val eight = 0.8  | 
   547 val six   = 0.6  | 
   547 val six   = 0.6  | 
   548   | 
   548   | 
   549 two - one == one  | 
   549 two - one == one  | 
   550 eight - six == two  | 
   550 eight - six == two  | 
   551   | 
   551 eight - six  | 
   552   | 
   552   | 
   553   | 
   553   | 
   554   | 
   554 // problems about equality and type-errors  | 
   555 List(1, 2, 3).contains("your cup") | 
   555   | 
         | 
   556 List(1, 2, 3).contains("your cup")   // should not compile, but retruns false | 
         | 
   557   | 
         | 
   558 List(1, 2, 3) == Vector(1, 2, 3)     // again should not compile, but returns true  | 
   556   | 
   559   | 
   557   | 
   560   | 
   558 // I like best about Scala that it lets me often write  | 
   561 // I like best about Scala that it lets me often write  | 
   559 // concise, readable code. And it hooks up with the   | 
   562 // concise, readable code. And it hooks up with the   | 
   560 // Isabelle theorem prover.   | 
   563 // Isabelle theorem prover.   | 
   561   | 
   564   | 
   562   | 
   565   | 
   563 // Puzzlers  | 
   566 // Puzzlers  | 
   564   | 
   567   | 
   565 val MONTH = 12  | 
   568 val month = 12  | 
   566 val DAY = 24  | 
   569 val day = 24  | 
   567 val (HOUR, MINUTE, SECOND) = (12, 0, 0)  | 
   570 val (hour, min, sec) = (12, 0, 0)  | 
   568   | 
   571   | 
   569 // use lowercase names for variable   | 
   572 // use lowercase names for variable   | 
   570   | 
   573   | 
   571   | 
   574   | 
   572 //==================  | 
   575 //==================  | 
   573 val oneTwo = Seq(1, 2, 3).permutations  | 
   576 val oneTwo = Seq(1, 2, 3).permutations  | 
   574   | 
   577   | 
   575 if (oneTwo.length > 0) { | 
   578 if (oneTwo.length > 0) { | 
   576   println("Permutations of 1 and 2:") | 
   579   println("Permutations of 1,2 and 3:") | 
   577   oneTwo.foreach(println)  | 
   580   oneTwo.foreach(println)  | 
   578 }  | 
   581 }  | 
   579   | 
   582   | 
   580 val threeFour = Seq(3, 4, 5).permutations  | 
   583 val threeFour = Seq(3, 4, 5).permutations  | 
   581   | 
   584   | 
   582 if (!threeFour.isEmpty) { | 
   585 if (!threeFour.isEmpty) { | 
   583   println("Permutations of 3 and 4:") | 
   586   println("Permutations of 3, 4 and 5:") | 
   584   threeFour.foreach(println)  | 
   587   threeFour.foreach(println)  | 
   585 }  | 
   588 }  | 
   586   | 
   589   | 
   587 //==================  | 
   590 //==================  | 
   588 val (a, b, c) =  | 
   591 val (a, b, c) =  |