progs/lecture5.scala
changeset 329 8a34b2ebc8cc
parent 328 0e591f806290
child 333 24bc76d97db2
equal deleted inserted replaced
328:0e591f806290 329:8a34b2ebc8cc
     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
   389 half + third
   391 half + third
   390 half / third
   392 half / third
   391 
   393 
   392 (1 / 3) + half
   394 (1 / 3) + half
   393 (1 / 2) + third
   395 (1 / 2) + third
   394 
       
   395 
       
   396 
   396 
   397 
   397 
   398 // DFAs in Scala  
   398 // DFAs in Scala  
   399 //===============
   399 //===============
   400 import scala.util.Try
   400 import scala.util.Try
   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) =
   608 //destined to fail at runtime.
   611 //destined to fail at runtime.
   609 
   612 
   610 
   613 
   611 //================
   614 //================
   612 // does not work anymore in 2.13.0
   615 // does not work anymore in 2.13.0
   613 val numbers = List("1", "2").toSet() + "3"
   616 val numbers = List("1", "2").toSet + "3"