progs/lecture5.scala
changeset 326 e5453add7df6
parent 247 50a3b874008a
child 328 0e591f806290
equal deleted inserted replaced
325:ca9c1cf929fa 326:e5453add7df6
     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 //==================================================
    98   case c::s => SEQ(CHAR(c), charlist2rexp(s))
    95   case c::s => SEQ(CHAR(c), charlist2rexp(s))
    99 }
    96 }
   100 implicit def string2rexp(s: String): Rexp = 
    97 implicit def string2rexp(s: String): Rexp = 
   101   charlist2rexp(s.toList)
    98   charlist2rexp(s.toList)
   102 
    99 
   103 
       
   104 implicit def RexpOps (r: Rexp) = new {
   100 implicit def RexpOps (r: Rexp) = new {
   105   def | (s: Rexp) = ALT(r, s)
   101   def | (s: Rexp) = ALT(r, s)
   106   def % = STAR(r)
   102   def % = STAR(r)
   107   def ~ (s: Rexp) = SEQ(r, s)
   103   def ~ (s: Rexp) = SEQ(r, s)
   108 }
   104 }
   128 //example regular expressions
   124 //example regular expressions
   129 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
   125 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
   130 val sign = "+" | "-" | ""
   126 val sign = "+" | "-" | ""
   131 val number = sign ~ digit ~ digit.% 
   127 val number = sign ~ digit ~ digit.% 
   132 
   128 
   133 // task: enumerate exhaustively regular expression
   129 // Task: enumerate exhaustively regular expressions
   134 // starting from small ones towards bigger ones.
   130 // starting from small ones towards bigger ones.
   135 
   131 
   136 // 1st idea: enumerate them all in a Set
   132 // 1st idea: enumerate them all in a Set
   137 // up to a level
   133 // up to a level
   138 
   134 
   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 //===============================
   306 // I hope you had fun!
   513 // I hope you had fun!
   307 
   514 
   308 // A function should do one thing, and only one thing.
   515 // A function should do one thing, and only one thing.
   309 
   516 
   310 // Make your variables immutable, unless there's a good 
   517 // Make your variables immutable, unless there's a good 
   311 // reason not to.
   518 // reason not to. Usually there is not.
   312 
   519 
   313 // I did it, but this is actually not a good reason:
   520 // I did it once, but this is actually not a good reason:
   314 // generating new labels:
   521 // generating new labels:
   315 
   522 
   316 var counter = -1
   523 var counter = -1
   317 
   524 
   318 def Fresh(x: String) = {
   525 def Fresh(x: String) = {
   323 Fresh("x")
   530 Fresh("x")
   324 Fresh("x")
   531 Fresh("x")
   325 
   532 
   326 
   533 
   327 
   534 
   328 // You can be productive on Day 1, but the language is deep.
   535 // I think you can be productive on Day 1, but the 
       
   536 // language is deep.
   329 //
   537 //
   330 // http://scalapuzzlers.com
   538 // http://scalapuzzlers.com
   331 //
   539 //
   332 // http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/
   540 // http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/
   333 
   541 
   334 List(1, 2, 3).contains("your mom")
   542 List(1, 2, 3).contains("your cup")
       
   543 
   335 
   544 
   336 // I like best about Scala that it lets me often write
   545 // I like best about Scala that it lets me often write
   337 // concise, readable code. And it hooks up with the 
   546 // concise, readable code. And it hooks up with the 
   338 // Isabelle theorem prover.
   547 // Isabelle theorem prover. 
   339 
   548 
       
   549 
       
   550 // Puzzlers
       
   551 
       
   552 val MONTH = 12
       
   553 val DAY = 24
       
   554 val (HOUR, MINUTE, SECOND) = (12, 0, 0)
       
   555 
       
   556 // use lowercase names for variable 
       
   557 
       
   558 
       
   559 //==================
       
   560 val oneTwo = Seq(1, 2, 3).permutations
       
   561 
       
   562 if (oneTwo.length > 0) {
       
   563   println("Permutations of 1 and 2:")
       
   564   oneTwo.foreach(println)
       
   565 }
       
   566 
       
   567 val threeFour = Seq(3, 4, 5).permutations
       
   568 
       
   569 if (!threeFour.isEmpty) {
       
   570   println("Permutations of 3 and 4:")
       
   571   threeFour.foreach(println)
       
   572 }
       
   573 
       
   574 //==================
       
   575 val (a, b, c) =
       
   576     if (4 < 5) {
       
   577         "bar"
       
   578     } else { 
       
   579         Some(10)
       
   580     }
       
   581 
       
   582 //Because when an expression has multiple return branches, Scala tries to
       
   583 //be helpful, by picking the first common ancestor type of all the
       
   584 //branches as the type of the whole expression.
       
   585 //
       
   586 //In this case, one branch has type String and the other has type
       
   587 //Option[Int], so the compiler decides that what the developer really
       
   588 //wants is for the whole if/else expression to have type Serializable,
       
   589 //since that’s the most specific type to claim both String and Option as
       
   590 //descendants.
       
   591 //
       
   592 //And guess what, Tuple3[A, B, C] is also Serializable, so as far as the
       
   593 //compiler is concerned, the assignment of the whole mess to (a, b, c)
       
   594 //can’t be proven invalid. So it gets through with a warning,
       
   595 //destined to fail at runtime.
       
   596 
       
   597 
       
   598 //================
       
   599 // does not work anymore in 2.13.0
       
   600 val numbers = List("1", "2").toSet() + "3"