|      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) = |