|      5  |      5  | 
|      6 // Laziness with style |      6 // Laziness with style | 
|      7 //===================== |      7 //===================== | 
|      8  |      8  | 
|      9 // The concept of lazy evaluation doesn’t really  |      9 // The concept of lazy evaluation doesn’t really  | 
|     10 // exist in non-functional languages, but it is  |     10 // exist in non-functional languages. C-like languages | 
|     11 // pretty easy to grasp. Consider first  |     11 // are strict. To see the difference, consider | 
|     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 // say we have a pretty expensive operation |     19 // In contrast, say we have a pretty expensive operation: | 
|         |     20  | 
|     20 def peop(n: BigInt): Boolean = peop(n + 1)  |     21 def peop(n: BigInt): Boolean = peop(n + 1)  | 
|     21  |     22  | 
|     22 val a = "foo" |     23 val a = "foo" | 
|     23 val b = "bar" |     24 val b = "foo" | 
|     24  |     25  | 
|     25 if (a == b || peop(0)) println("true") else println("false") |     26 if (a == b || peop(0)) println("true") else println("false") | 
|     26  |     27  | 
|     27 // this is called lazy evaluation |     28 // This is called "lazy evaluation": | 
|     28 // you delay compuation until it is really  |     29 // you delay compuation until it is really  | 
|     29 // needed; once calculated though, does not  |     30 // needed. Once calculated though, the result | 
|     30 // need to be re-calculated |     31 // does not need to be re-calculated. | 
|     31  |     32  | 
|     32 // a useful example is |     33 // A useful example is | 
|     33 def time_needed[T](i: Int, code: => T) = { |     34 def time_needed[T](i: Int, code: => T) = { | 
|     34   val start = System.nanoTime() |     35   val start = System.nanoTime() | 
|     35   for (j <- 1 to i) code |     36   for (j <- 1 to i) code | 
|     36   val end = System.nanoTime() |     37   val end = System.nanoTime() | 
|     37   f"${(end - start) / (i * 1.0e9)}%.6f secs" |     38   f"${(end - start) / (i * 1.0e9)}%.6f secs" | 
|     38 } |     39 } | 
|     39  |     40  | 
|     40  |     41 // A slightly less obvious example: Prime Numbers. | 
|     41 // streams (I do not care how many) |     42 // (I do not care how many) primes: 2, 3, 5, 7, 9, 11, 13 .... | 
|     42 // primes: 2, 3, 5, 7, 9, 11, 13 .... |     43  | 
|     43  |     44 def generatePrimes (s: LazyList[Int]): LazyList[Int] = | 
|     44 def generatePrimes (s: Stream[Int]): Stream[Int] = |         | 
|     45   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0)) |     45   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0)) | 
|     46  |     46  | 
|     47 val primes = generatePrimes(Stream.from(2)) |     47 val primes = generatePrimes(LazyList.from(2)) | 
|     48  |     48  | 
|     49 // the first 10 primes |     49 // the first 10 primes | 
|     50 primes.take(10).par.toList |     50 primes.take(10).toList | 
|     51  |     51  | 
|     52 time_needed(1, primes.filter(_ > 100).take(3000).toList) |     52 time_needed(1, primes.filter(_ > 100).take(3000).toList) | 
|     53 time_needed(1, primes.filter(_ > 100).take(1000).toList) |     53 time_needed(1, primes.filter(_ > 100).take(3000).toList) | 
|     54  |     54  | 
|     55 // a stream of successive numbers |     55 // A Stream (LazyList) of successive numbers: | 
|     56  |     56  | 
|     57 Stream.from(2).print |     57 LazyList.from(2).take(10) | 
|     58 Stream.from(2).take(10).force |     58 LazyList.from(2).take(10).force | 
|     59 Stream.from(2).take(10).print |     59  | 
|     60 Stream.from(10).take(10).print |     60 // An Iterative version of the Fibonacci numbers | 
|     61  |     61 def fibIter(a: BigInt, b: BigInt): LazyList[BigInt] = | 
|     62 Stream.from(2).take(10).force |         | 
|     63  |         | 
|     64 // iterative version of the Fibonacci numbers |         | 
|     65 def fibIter(a: BigInt, b: BigInt): Stream[BigInt] = |         | 
|     66   a #:: fibIter(b, a + b) |     62   a #:: fibIter(b, a + b) | 
|     67  |     63  | 
|     68  |     64  | 
|     69 fibIter(1, 1).take(10).force |     65 fibIter(1, 1).take(10).force | 
|     70 fibIter(8, 13).take(10).force |     66 fibIter(8, 13).take(10).force | 
|     71  |     67  | 
|     72 fibIter(1, 1).drop(10000).take(1).print |     68 fibIter(1, 1).drop(10000).take(1) | 
|     73  |     69 fibIter(1, 1).drop(10000).take(1).force | 
|     74  |     70  | 
|     75 // good for testing |     71  | 
|         |     72 // LazyLists are good for testing | 
|     76  |     73  | 
|     77  |     74  | 
|     78 // Regular expressions - the power of DSLs in Scala |     75 // Regular expressions - the power of DSLs in Scala | 
|     79 //                                     and Laziness |     76 //                                     and Laziness | 
|     80 //================================================== |     77 //================================================== | 
|    147 } |    143 } | 
|    148  |    144  | 
|    149 enuml(1, "a") |    145 enuml(1, "a") | 
|    150 enuml(1, "a").size |    146 enuml(1, "a").size | 
|    151 enuml(2, "a").size |    147 enuml(2, "a").size | 
|    152 enuml(3, "a").size  |    148 enuml(3, "a").size // out of heap space | 
|    153 enuml(4, "a").size // out of heap space |    149  | 
|    154  |    150  | 
|    155  |    151  | 
|    156 def enum(rs: Stream[Rexp]) : Stream[Rexp] =  |    152 def enum(rs: LazyList[Rexp]) : LazyList[Rexp] =  | 
|    157   rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #::: |    153   rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #::: | 
|    158                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #::: |    154                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #::: | 
|    159                 (for (r1 <- rs) yield STAR(r1)) ) |    155                 (for (r1 <- rs) yield STAR(r1)) ) | 
|    160  |    156  | 
|    161  |    157  | 
|    162 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200).force |    158 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force | 
|    163 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(5000000) |    159 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5000000) | 
|    164  |    160  | 
|    165  |    161  | 
|    166 val is =  |    162 val is =  | 
|    167   (enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)) |    163   (enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))) | 
|    168     .dropWhile(depth(_) < 3) |    164     .dropWhile(depth(_) < 3) | 
|    169     .take(10).foreach(println)) |    165     .take(10).foreach(println)) | 
|    170  |    166  | 
|    171  |    167  | 
|    172  |    168 // Polymorphic Types | 
|    173 // Parsing - The Solved Problem That Isn't |    169 //=================== | 
|    174 //========================================= |    170  | 
|         |    171 // You do not want to write functions like contains, first,  | 
|         |    172 // length and so on for every type of lists. | 
|         |    173  | 
|         |    174  | 
|         |    175 def length_string_list(lst: List[String]): Int = lst match { | 
|         |    176   case Nil => 0 | 
|         |    177   case x::xs => 1 + length_string_list(xs) | 
|         |    178 } | 
|         |    179  | 
|         |    180 def length_int_list(lst: List[Int]): Int = lst match { | 
|         |    181   case Nil => 0 | 
|         |    182   case x::xs => 1 + length_int_list(xs) | 
|         |    183 } | 
|         |    184  | 
|         |    185 length_string_list(List("1", "2", "3", "4")) | 
|         |    186 length_int_list(List(1, 2, 3, 4)) | 
|         |    187  | 
|         |    188 // you can make the function parametric in type(s) | 
|         |    189  | 
|         |    190 def length[A](lst: List[A]): Int = lst match { | 
|         |    191   case Nil => 0 | 
|         |    192   case x::xs => 1 + length(xs) | 
|         |    193 } | 
|         |    194 length(List("1", "2", "3", "4")) | 
|         |    195 length(List(1, 2, 3, 4)) | 
|         |    196  | 
|         |    197  | 
|         |    198 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { | 
|         |    199   case Nil => Nil | 
|         |    200   case x::xs => f(x)::map(xs, f)  | 
|         |    201 } | 
|         |    202  | 
|         |    203 map(List(1, 2, 3, 4), (x: Int) => x.toString) | 
|         |    204  | 
|         |    205  | 
|         |    206  | 
|         |    207 // distinct / distinctBy | 
|         |    208  | 
|         |    209 val ls = List(1,2,3,3,2,4,3,2,1) | 
|         |    210 ls.distinct | 
|         |    211  | 
|         |    212 // .minBy(_._2) | 
|         |    213 // .sortBy(_._1) | 
|         |    214  | 
|         |    215 def distinctBy[B, C](xs: List[B],  | 
|         |    216                      f: B => C,  | 
|         |    217                      acc: List[C] = Nil): List[B] = xs match { | 
|         |    218   case Nil => Nil | 
|         |    219   case x::xs => { | 
|         |    220     val res = f(x) | 
|         |    221     if (acc.contains(res)) distinctBy(xs, f, acc)   | 
|         |    222     else x::distinctBy(xs, f, res::acc) | 
|         |    223   } | 
|         |    224 }  | 
|         |    225  | 
|         |    226 val cs = List('A', 'b', 'a', 'c', 'B', 'D', 'd') | 
|         |    227  | 
|         |    228 distinctBy(cs, (c:Char) => c.toUpper) | 
|         |    229  | 
|         |    230 // since 2.13 | 
|         |    231  | 
|         |    232 cs.distinctBy((c:Char) => c.toUpper) | 
|         |    233  | 
|         |    234  | 
|         |    235 // Type inference is local in Scala | 
|         |    236  | 
|         |    237 def id[T](x: T) : T = x | 
|         |    238  | 
|         |    239 val x = id(322)          // Int | 
|         |    240 val y = id("hey")        // String | 
|         |    241 val z = id(Set(1,2,3,4)) // Set[Int] | 
|         |    242  | 
|         |    243  | 
|         |    244  | 
|         |    245 // The type variable concept in Scala can get really complicated. | 
|    175 // |    246 // | 
|    176 // https://tratt.net/laurie/blog/entries/parsing_the_solved_problem_that_isnt.html |    247 // - variance (OO) | 
|         |    248 // - bounds (subtyping) | 
|         |    249 // - quantification | 
|         |    250  | 
|         |    251 // Java has issues with this too: Java allows | 
|         |    252 // to write the following incorrect code, and | 
|         |    253 // only recovers by raising an exception | 
|         |    254 // at runtime. | 
|         |    255  | 
|         |    256 // Object[] arr = new Integer[10]; | 
|         |    257 // arr[0] = "Hello World"; | 
|         |    258  | 
|         |    259  | 
|         |    260 // Scala gives you a compile-time error, which | 
|         |    261 // is much better. | 
|         |    262  | 
|         |    263 var arr = Array[Int]() | 
|         |    264 arr(0) = "Hello World" | 
|         |    265  | 
|         |    266  | 
|         |    267  | 
|         |    268 // (Immutable) | 
|         |    269 // Object Oriented Programming in Scala | 
|    177 // |    270 // | 
|    178 // Or, A topic of endless "fun"(?) |    271 // ===================================== | 
|    179  |    272  | 
|    180  |    273 abstract class Animal | 
|    181 // input type: String |    274 case class Bird(name: String) extends Animal { | 
|    182 // output type: Int |    275    override def toString = name | 
|    183 Integer.parseInt("123u456") |    276 } | 
|    184  |    277 case class Mammal(name: String) extends Animal | 
|    185 /* Note, in the previous lectures I did not show the type consraint |    278 case class Reptile(name: String) extends Animal | 
|    186  * I <% Seq[_] , which means that the input type I can be |    279  | 
|    187  * treated, or seen, as a sequence. */ |    280 Mammal("Zebra") | 
|    188  |    281 println(Mammal("Zebra")) | 
|    189 abstract class Parser[I <% Seq[_], T] { |    282 println(Mammal("Zebra").toString) | 
|    190   def parse(ts: I): Set[(T, I)] |    283  | 
|    191  |    284  | 
|    192   def parse_all(ts: I) : Set[T] = |    285 Bird("Sparrow") | 
|    193     for ((head, tail) <- parse(ts);  |    286 println(Bird("Sparrow")) | 
|    194         if (tail.isEmpty)) yield head |    287 println(Bird("Sparrow").toString) | 
|    195 } |    288  | 
|    196  |    289  | 
|    197 // the idea is that a parser can parse something |    290 // There is a very convenient short-hand notation | 
|    198 // from the input and leaves something unparsed => pairs |    291 // for constructors: | 
|    199  |    292  | 
|    200 class AltParser[I <% Seq[_], T]( |    293 class Fraction(x: Int, y: Int) { | 
|    201   p: => Parser[I, T],  |    294   def numer = x | 
|    202   q: => Parser[I, T]) extends Parser[I, T] { |    295   def denom = y | 
|    203  |    296 } | 
|    204   def parse(sb: I) = p.parse(sb) ++ q.parse(sb)    |    297  | 
|    205 } |    298 val half = new Fraction(1, 2) | 
|    206  |    299  | 
|    207  |    300 case class Fraction(numer: Int, denom: Int) | 
|    208 class SeqParser[I <% Seq[_], T, S]( |    301  | 
|    209   p: => Parser[I, T],  |    302 val half = Fraction(1, 2) | 
|    210   q: => Parser[I, S]) extends Parser[I, (T, S)] { |    303  | 
|    211  |    304 half.denom | 
|    212   def parse(sb: I) =  |    305  | 
|    213     for ((head1, tail1) <- p.parse(sb);  |    306  | 
|    214          (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2) |    307 // In mandelbrot.scala I used complex (imaginary) numbers  | 
|    215 } |    308 // and implemented the usual arithmetic operations for complex  | 
|    216  |    309 // numbers. | 
|    217  |    310  | 
|    218 class FunParser[I <% Seq[_], T, S]( |    311 case class Complex(re: Double, im: Double) {  | 
|    219   p: => Parser[I, T],  |    312   // represents the complex number re + im * i | 
|    220   f: T => S) extends Parser[I, S] { |    313   def +(that: Complex) = Complex(this.re + that.re, this.im + that.im) | 
|    221  |    314   def -(that: Complex) = Complex(this.re - that.re, this.im - that.im) | 
|    222   def parse(sb: I) =  |    315   def *(that: Complex) = Complex(this.re * that.re - this.im * that.im, | 
|    223     for ((head, tail) <- p.parse(sb)) yield (f(head), tail) |    316                                  this.re * that.im + that.re * this.im) | 
|    224 } |    317   def *(that: Double) = Complex(this.re * that, this.im * that) | 
|    225  |    318   def abs = Math.sqrt(this.re * this.re + this.im * this.im) | 
|    226  |    319 } | 
|    227 // atomic parsers   |    320  | 
|    228 case class CharParser(c: Char) extends Parser[String, Char] { |    321 val test = Complex(1, 2) + Complex (3, 4) | 
|    229   def parse(sb: String) =  |    322  | 
|    230     if (sb != "" && sb.head == c) Set((c, sb.tail)) else Set() |    323 // this could have equally been written as | 
|    231 } |    324 val test = Complex(1, 2).+(Complex (3, 4)) | 
|    232  |    325  | 
|    233 import scala.util.matching.Regex |    326 // this applies to all methods, but requires | 
|    234 case class RegexParser(reg: Regex) extends Parser[String, String] { |    327 import scala.language.postfixOps | 
|    235   def parse(sb: String) = reg.findPrefixMatchOf(sb) match { |    328  | 
|    236     case None => Set() |    329 List(5, 2, 3, 4).sorted | 
|    237     case Some(m) => Set((m.matched, m.after.toString))   |    330 List(5, 2, 3, 4) sorted | 
|         |    331  | 
|         |    332  | 
|         |    333 // ...to allow the notation n + m * i | 
|         |    334 import scala.language.implicitConversions    | 
|         |    335  | 
|         |    336 val i = Complex(0, 1) | 
|         |    337 implicit def double2complex(re: Double) = Complex(re, 0) | 
|         |    338  | 
|         |    339  | 
|         |    340 val inum1 = -2.0 + -1.5 * i | 
|         |    341 val inum2 =  1.0 +  1.5 * i | 
|         |    342  | 
|         |    343  | 
|         |    344  | 
|         |    345 // All is public by default....so no public is needed. | 
|         |    346 // You can have the usual restrictions about private  | 
|         |    347 // values and methods, if you are MUTABLE !!! | 
|         |    348  | 
|         |    349 case class BankAccount(init: Int) { | 
|         |    350  | 
|         |    351   private var balance = init | 
|         |    352  | 
|         |    353   def deposit(amount: Int): Unit = { | 
|         |    354     if (amount > 0) balance = balance + amount | 
|    238   } |    355   } | 
|    239 } |    356  | 
|    240  |    357   def withdraw(amount: Int): Int = | 
|    241 val NumParser = RegexParser("[0-9]+".r) |    358     if (0 < amount && amount <= balance) { | 
|    242 def StringParser(s: String) = RegexParser(Regex.quote(s).r) |    359       balance = balance - amount | 
|    243  |    360       balance | 
|    244 NumParser.parse_all("12u345") |    361     } else throw new Error("insufficient funds") | 
|    245 println(NumParser.parse_all("12u45")) |    362 } | 
|    246  |    363  | 
|    247  |    364 // BUT since we are completely IMMUTABLE, this is  | 
|    248 // convenience |    365 // virtually of not concern to us. | 
|    249 implicit def string2parser(s: String) = StringParser(s) |    366  | 
|    250 implicit def char2parser(c: Char) = CharParser(c) |    367  | 
|    251  |    368  | 
|    252 implicit def ParserOps[I<% Seq[_], T](p: Parser[I, T]) = new { |    369 // another example about Fractions | 
|    253   def | (q : => Parser[I, T]) = new AltParser[I, T](p, q) |    370 import scala.language.implicitConversions | 
|    254   def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f) |    371 import scala.language.reflectiveCalls | 
|    255   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q) |    372  | 
|    256 } |    373  | 
|    257  |    374 case class Fraction(numer: Int, denom: Int) { | 
|    258 implicit def StringOps(s: String) = new { |    375   override def toString = numer.toString + "/" + denom.toString | 
|    259   def | (q : => Parser[String, String]) = new AltParser[String, String](s, q) |    376  | 
|    260   def | (r: String) = new AltParser[String, String](s, r) |    377   def +(other: Fraction) = Fraction(numer + other.numer, denom + other.denom) | 
|    261   def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f) |    378   def /(other: Fraction) = Fraction(numer * other.denom, denom * other.numer) | 
|    262   def ~[S] (q : => Parser[String, S]) =  |    379  } | 
|    263     new SeqParser[String, String, S](s, q) |    380  | 
|    264   def ~ (r: String) =  |    381 implicit def Int2Fraction(x: Int) = Fraction(x, 1) | 
|    265     new SeqParser[String, String, String](s, r) |    382  | 
|    266 } |    383  | 
|    267  |    384 val half = Fraction(1, 2) | 
|    268  |    385 val third = Fraction (1, 3) | 
|    269 val NumParserInt = NumParser ==> (s => 2 * s.toInt) |    386  | 
|    270  |    387 half + third | 
|    271 NumParser.parse_all("12345") |    388 half / third | 
|    272 NumParserInt.parse_all("12345") |    389  | 
|    273 NumParserInt.parse_all("12u45") |    390 (1 / 3) + half | 
|    274  |    391 (1 / 2) + third | 
|    275  |    392  | 
|    276 // grammar for arithmetic expressions |    393  | 
|    277 // |    394  | 
|    278 //  E ::= T + E | T - E | T |    395  | 
|    279 //  T ::= F * T | F |    396 // DFAs in Scala   | 
|    280 //  F ::= ( E ) | Number |    397 //=============== | 
|    281  |    398 import scala.util.Try | 
|    282  |    399  | 
|    283 lazy val E: Parser[String, Int] =  |    400  | 
|    284   (T ~ "+" ~ E) ==> { case ((x, y), z) => x + z } | |    401 // A is the state type | 
|    285   (T ~ "-" ~ E) ==> { case ((x, y), z) => x - z } | T  |    402 // C is the input (usually characters) | 
|    286 lazy val T: Parser[String, Int] =  |    403  | 
|    287   (F ~ "*" ~ T) ==> { case ((x, y), z) => x * z } | F |    404 case class DFA[A, C](start: A,              // starting state | 
|    288 lazy val F: Parser[String, Int] =  |    405                      delta: (A, C) => A,    // transition function | 
|    289   ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } | NumParserInt |    406                      fins:  A => Boolean) { // final states (Set) | 
|    290  |    407  | 
|    291  |    408   def deltas(q: A, s: List[C]) : A = s match { | 
|    292 println(E.parse_all("4*2+3")) |    409     case Nil => q | 
|    293 println(E.parse_all("4*(2+3)")) |    410     case c::cs => deltas(delta(q, c), cs) | 
|    294 println(E.parse_all("(4)*((2+3))")) |    411   } | 
|    295 println(E.parse_all("4/2+3")) |    412  | 
|    296 println(E.parse_all("(1+2)+3")) |    413   def accepts(s: List[C]) : Boolean =  | 
|    297 println(E.parse_all("1+2+3"))  |    414     Try(fins(deltas(start, s))) getOrElse false | 
|    298  |    415 } | 
|    299  |    416  | 
|         |    417 // the example shown in the handout  | 
|         |    418 abstract class State | 
|         |    419 case object Q0 extends State | 
|         |    420 case object Q1 extends State | 
|         |    421 case object Q2 extends State | 
|         |    422 case object Q3 extends State | 
|         |    423 case object Q4 extends State | 
|         |    424  | 
|         |    425 val delta : (State, Char) => State =  | 
|         |    426   { case (Q0, 'a') => Q1 | 
|         |    427     case (Q0, 'b') => Q2 | 
|         |    428     case (Q1, 'a') => Q4 | 
|         |    429     case (Q1, 'b') => Q2 | 
|         |    430     case (Q2, 'a') => Q3 | 
|         |    431     case (Q2, 'b') => Q2 | 
|         |    432     case (Q3, 'a') => Q4 | 
|         |    433     case (Q3, 'b') => Q0 | 
|         |    434     case (Q4, 'a') => Q4 | 
|         |    435     case (Q4, 'b') => Q4  | 
|         |    436     case _ => throw new Exception("Undefined") } | 
|         |    437  | 
|         |    438 val dfa = DFA(Q0, delta, Set[State](Q4)) | 
|         |    439  | 
|         |    440 dfa.accepts("abaaa".toList)     // true | 
|         |    441 dfa.accepts("bbabaab".toList)   // true | 
|         |    442 dfa.accepts("baba".toList)      // false | 
|         |    443 dfa.accepts("abc".toList)       // false | 
|         |    444  | 
|         |    445  | 
|         |    446 // NFAs (Nondeterministic Finite Automata) | 
|         |    447  | 
|         |    448  | 
|         |    449 case class NFA[A, C](starts: Set[A],          // starting states | 
|         |    450                      delta: (A, C) => Set[A], // transition function | 
|         |    451                      fins:  A => Boolean) {   // final states  | 
|         |    452  | 
|         |    453   // given a state and a character, what is the set of  | 
|         |    454   // next states? if there is none => empty set | 
|         |    455   def next(q: A, c: C) : Set[A] =  | 
|         |    456     Try(delta(q, c)) getOrElse Set[A]()  | 
|         |    457  | 
|         |    458   def nexts(qs: Set[A], c: C) : Set[A] = | 
|         |    459     qs.flatMap(next(_, c)) | 
|         |    460  | 
|         |    461   // depth-first version of accepts | 
|         |    462   def search(q: A, s: List[C]) : Boolean = s match { | 
|         |    463     case Nil => fins(q) | 
|         |    464     case c::cs => next(q, c).exists(search(_, cs)) | 
|         |    465   } | 
|         |    466  | 
|         |    467   def accepts(s: List[C]) : Boolean = | 
|         |    468     starts.exists(search(_, s)) | 
|         |    469 } | 
|         |    470  | 
|         |    471  | 
|         |    472  | 
|         |    473 // NFA examples | 
|         |    474  | 
|         |    475 val nfa_trans1 : (State, Char) => Set[State] =  | 
|         |    476   { case (Q0, 'a') => Set(Q0, Q1)  | 
|         |    477     case (Q0, 'b') => Set(Q2)  | 
|         |    478     case (Q1, 'a') => Set(Q1)  | 
|         |    479     case (Q2, 'b') => Set(Q2) } | 
|         |    480  | 
|         |    481 val nfa = NFA(Set[State](Q0), nfa_trans1, Set[State](Q2)) | 
|         |    482  | 
|         |    483 nfa.accepts("aa".toList)             // false | 
|         |    484 nfa.accepts("aaaaa".toList)          // false | 
|         |    485 nfa.accepts("aaaaab".toList)         // true | 
|         |    486 nfa.accepts("aaaaabbb".toList)       // true | 
|         |    487 nfa.accepts("aaaaabbbaaa".toList)    // false | 
|         |    488 nfa.accepts("ac".toList)             // false | 
|         |    489  | 
|         |    490  | 
|         |    491 // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs? | 
|         |    492 // A: Subset construction. Here the state type for the DFA is | 
|         |    493 //    sets of states. | 
|         |    494  | 
|         |    495 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = { | 
|         |    496   DFA(nfa.starts,  | 
|         |    497       { case (qs, c) => nfa.nexts(qs, c) },  | 
|         |    498       _.exists(nfa.fins)) | 
|         |    499 } | 
|         |    500  | 
|         |    501 subset(nfa).accepts("aa".toList)             // false | 
|         |    502 subset(nfa).accepts("aaaaa".toList)          // false | 
|         |    503 subset(nfa).accepts("aaaaab".toList)         // true | 
|         |    504 subset(nfa).accepts("aaaaabbb".toList)       // true | 
|         |    505 subset(nfa).accepts("aaaaabbbaaa".toList)    // false | 
|         |    506 subset(nfa).accepts("ac".toList)             // false | 
|    300  |    507  | 
|    301  |    508  | 
|    302  |    509  | 
|    303 // The End ... Almost Christmas |    510 // The End ... Almost Christmas | 
|    304 //=============================== |    511 //=============================== |