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