progs/lecture5.scala
changeset 240 b8cdaf51ffef
parent 238 046f37a262d0
child 242 e6b34f617915
equal deleted inserted replaced
239:0c752ac51cfa 240:b8cdaf51ffef
     4 
     4 
     5 
     5 
     6 // Laziness with style
     6 // Laziness with style
     7 //=====================
     7 //=====================
     8 
     8 
     9 // The concept of lazy evaluation doesn’t really exist in 
     9 // The concept of lazy evaluation doesn’t really 
    10 // non-functional languages, but it is pretty easy to grasp. 
    10 // exist in non-functional languages, but it is 
    11 // Consider first 
    11 // pretty easy to grasp. Consider first 
    12 
    12 
    13 def square(x: Int) = x * x
    13 def square(x: Int) = x * x
    14 
    14 
    15 square(42 + 8)
    15 square(42 + 8)
    16 
    16 
    17 // this is called strict evaluation
    17 // this is called strict evaluation
    18 
    18 
    19 // pretty expensive operation
    19 // say we have a pretty expensive operation
    20 def peop(n: BigInt): Boolean = peop(n + 1) 
    20 def peop(n: BigInt): Boolean = peop(n + 1) 
       
    21 
    21 val a = "foo"
    22 val a = "foo"
    22 val b = "foo"
    23 val b = "foo"
    23 
    24 
    24 if (a == b || peop(0)) println("true") else println("false")
    25 if (a == b || peop(0)) println("true") else println("false")
    25 
    26 
    41 // primes: 2, 3, 5, 7, 9, 11, 13 ....
    42 // primes: 2, 3, 5, 7, 9, 11, 13 ....
    42 
    43 
    43 def generatePrimes (s: Stream[Int]): Stream[Int] =
    44 def generatePrimes (s: Stream[Int]): Stream[Int] =
    44   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))
    45   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))
    45 
    46 
    46 val primes: Stream[Int] = generatePrimes(Stream.from(2))
    47 val primes = generatePrimes(Stream.from(2))
    47 
    48 
    48 // the first 10 primes
    49 // the first 10 primes
    49 primes.take(10).toList
    50 primes.take(10).toList
    50 
    51 
    51 //primes.filter(_ > 100).take(2000).toList
       
    52 
       
    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 
    55 // a stream of successive numbers
    57 Stream.from(2)
    56 Stream.from(2)
       
    57 
    58 Stream.from(2).take(10)
    58 Stream.from(2).take(10)
    59 Stream.from(2).take(10).print
    59 Stream.from(2).take(10).print
    60 Stream.from(10).take(10).print
    60 Stream.from(10).take(10).print
    61 
    61 
    62 Stream.from(2).take(10).force
    62 Stream.from(2).take(10).force
    63 
    63 
    64 // itterative version of the Fibonacci numbers
    64 // iterative version of the Fibonacci numbers
    65 def fibIter(a: BigInt, b: BigInt): Stream[BigInt] =
    65 def fibIter(a: BigInt, b: BigInt): Stream[BigInt] =
    66   a #:: fibIter(b, a + b)
    66   a #:: fibIter(b, a + b)
    67 
    67 
    68 
    68 
    69 fibIter(1, 1).take(10).force
    69 fibIter(1, 1).take(10).force
    86 case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
    86 case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
    87 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
    87 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
    88 case class STAR(r: Rexp) extends Rexp             // star         r*
    88 case class STAR(r: Rexp) extends Rexp             // star         r*
    89 
    89 
    90 
    90 
    91 
       
    92 // writing (ab)* in the format above is 
       
    93 // tedious
       
    94 val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
       
    95 
       
    96 
       
    97 // some convenience for typing in regular expressions
    91 // some convenience for typing in regular expressions
    98 import scala.language.implicitConversions    
    92 import scala.language.implicitConversions    
    99 import scala.language.reflectiveCalls 
    93 import scala.language.reflectiveCalls 
   100 
    94 
   101 def charlist2rexp(s: List[Char]): Rexp = s match {
    95 def charlist2rexp(s: List[Char]): Rexp = s match {
   105 }
    99 }
   106 implicit def string2rexp(s: String): Rexp = 
   100 implicit def string2rexp(s: String): Rexp = 
   107   charlist2rexp(s.toList)
   101   charlist2rexp(s.toList)
   108 
   102 
   109 
   103 
   110 val r1 = STAR("ab")
       
   111 val r2 = STAR(ALT("ab", "baa baa black sheep"))
       
   112 val r3 = STAR(SEQ("ab", ALT("a", "b")))
       
   113 
       
   114 implicit def RexpOps (r: Rexp) = new {
   104 implicit def RexpOps (r: Rexp) = new {
   115   def | (s: Rexp) = ALT(r, s)
   105   def | (s: Rexp) = ALT(r, s)
   116   def % = STAR(r)
   106   def % = STAR(r)
   117   def ~ (s: Rexp) = SEQ(r, s)
   107   def ~ (s: Rexp) = SEQ(r, s)
   118 }
   108 }
   119 
       
   120 
   109 
   121 implicit def stringOps (s: String) = new {
   110 implicit def stringOps (s: String) = new {
   122   def | (r: Rexp) = ALT(s, r)
   111   def | (r: Rexp) = ALT(s, r)
   123   def | (r: String) = ALT(s, r)
   112   def | (r: String) = ALT(s, r)
   124   def % = STAR(s)
   113   def % = STAR(s)
   142 val number = sign ~ digit ~ digit.% 
   131 val number = sign ~ digit ~ digit.% 
   143 
   132 
   144 // task: enumerate exhaustively regular expression
   133 // task: enumerate exhaustively regular expression
   145 // starting from small ones towards bigger ones.
   134 // starting from small ones towards bigger ones.
   146 
   135 
   147 // 1st idea: enumerate them up to a level
   136 // 1st idea: enumerate them all in a Set
       
   137 // up to a level
   148 
   138 
   149 def enuml(l: Int, s: String) : Set[Rexp] = l match {
   139 def enuml(l: Int, s: String) : Set[Rexp] = l match {
   150   case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet
   140   case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet
   151   case n =>  
   141   case n =>  
   152     val rs = enuml(n - 1, s)
   142     val rs = enuml(n - 1, s)
   154     (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++
   144     (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++
   155     (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++
   145     (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++
   156     (for (r1 <- rs) yield STAR(r1))
   146     (for (r1 <- rs) yield STAR(r1))
   157 }
   147 }
   158 
   148 
       
   149 enuml(1, "a")
   159 enuml(1, "a").size
   150 enuml(1, "a").size
   160 enuml(2, "a").size
   151 enuml(2, "a").size
   161 enuml(3, "a").size // out of heap space
   152 enuml(3, "a").size 
       
   153 enuml(4, "a").size // out of heap space
   162 
   154 
   163 
   155 
   164 def enum(rs: Stream[Rexp]) : Stream[Rexp] = 
   156 def enum(rs: Stream[Rexp]) : Stream[Rexp] = 
   165   rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #:::
   157   rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #:::
   166                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::
   158                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::
   167                 (for (r1 <- rs) yield STAR(r1)) )
   159                 (for (r1 <- rs) yield STAR(r1)) )
   168 
   160 
   169 
   161 
   170 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200).force
   162 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200).force
   171 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200000).force
   163 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(5000000)
   172 
   164 
   173 
   165 
   174 val is = 
   166 val is = 
   175   (enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR))
   167   (enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR))
   176     .dropWhile(depth(_) < 3)
   168     .dropWhile(depth(_) < 3)
   323 
   315 
   324 
   316 
   325 
   317 
   326 
   318 
   327 
   319 
   328 // The End ... Almost Christimas
   320 // The End ... Almost Christmas
   329 //===============================
   321 //===============================
   330 
   322 
   331 // I hope you had fun!
   323 // I hope you had fun!
   332 
   324 
   333 // A function should do one thing, and only one thing.
   325 // A function should do one thing, and only one thing.
   334 
   326 
   335 // Make your variables immutable, unless there's a good 
   327 // Make your variables immutable, unless there's a good 
   336 // reason not to.
   328 // reason not to.
   337 
   329 
   338 // I did it, but this is actually not a good reason:
   330 // I did it, but this is actually not a good reason:
   339 // generating new labels
   331 // generating new labels:
       
   332 
   340 var counter = -1
   333 var counter = -1
   341 
   334 
   342 def Fresh(x: String) = {
   335 def Fresh(x: String) = {
   343   counter += 1
   336   counter += 1
   344   x ++ "_" ++ counter.toString()
   337   x ++ "_" ++ counter.toString()