| 
     1 // Scala Lecture 5  | 
         | 
     2 //=================  | 
         | 
     3   | 
         | 
     4   | 
         | 
     5   | 
         | 
     6 // Laziness with style  | 
         | 
     7 //=====================  | 
         | 
     8   | 
         | 
     9 // The concept of lazy evaluation doesn’t really exist in   | 
         | 
    10 // non-functional languages, but it is pretty easy to grasp.   | 
         | 
    11 // Consider first   | 
         | 
    12   | 
         | 
    13 def square(x: Int) = x * x  | 
         | 
    14   | 
         | 
    15 square(42 + 8)  | 
         | 
    16   | 
         | 
    17 // this is called strict evaluation  | 
         | 
    18   | 
         | 
    19 // pretty expensive operation  | 
         | 
    20 def peop(n: BigInt): Boolean = peop(n + 1)   | 
         | 
    21 val a = "foo"  | 
         | 
    22 val b = "foo"  | 
         | 
    23   | 
         | 
    24 if (a == b || peop(0)) println("true") else println("false") | 
         | 
    25   | 
         | 
    26 // this is called lazy evaluation  | 
         | 
    27 // you delay compuation until it is really   | 
         | 
    28 // needed; once calculated though, does not   | 
         | 
    29 // need to be re-calculated  | 
         | 
    30   | 
         | 
    31 // a useful example is  | 
         | 
    32 def time_needed[T](i: Int, code: => T) = { | 
         | 
    33   val start = System.nanoTime()  | 
         | 
    34   for (j <- 1 to i) code  | 
         | 
    35   val end = System.nanoTime()  | 
         | 
    36   f"${(end - start) / (i * 1.0e9)}%.6f secs" | 
         | 
    37 }  | 
         | 
    38   | 
         | 
    39   | 
         | 
    40 // streams (I do not care how many)  | 
         | 
    41 // primes: 2, 3, 5, 7, 9, 11, 13 ....  | 
         | 
    42   | 
         | 
    43 def generatePrimes (s: Stream[Int]): Stream[Int] =  | 
         | 
    44   s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))  | 
         | 
    45   | 
         | 
    46 val primes: Stream[Int] = generatePrimes(Stream.from(2))  | 
         | 
    47   | 
         | 
    48 // the first 10 primes  | 
         | 
    49 primes.take(10).toList  | 
         | 
    50   | 
         | 
    51 //primes.filter(_ > 100).take(2000).toList  | 
         | 
    52   | 
         | 
    53 time_needed(1, primes.filter(_ > 100).take(3000).toList)  | 
         | 
    54 time_needed(1, primes.filter(_ > 100).take(3000).toList)  | 
         | 
    55   | 
         | 
    56   | 
         | 
    57 Stream.from(2)  | 
         | 
    58 Stream.from(2).take(10)  | 
         | 
    59 Stream.from(2).take(10).print  | 
         | 
    60 Stream.from(10).take(10).print  | 
         | 
    61   | 
         | 
    62 Stream.from(2).take(10).force  | 
         | 
    63   | 
         | 
    64 // itterative version of the Fibonacci numbers  | 
         | 
    65 def fibIter(a: BigInt, b: BigInt): Stream[BigInt] =  | 
         | 
    66   a #:: fibIter(b, a + b)  | 
         | 
    67   | 
         | 
    68   | 
         | 
    69 fibIter(1, 1).take(10).force  | 
         | 
    70 fibIter(8, 13).take(10).force  | 
         | 
    71   | 
         | 
    72 fibIter(1, 1).drop(10000).take(1).print  | 
         | 
    73   | 
         | 
    74   | 
         | 
    75 // good for testing  | 
         | 
    76   | 
         | 
    77   | 
         | 
    78 // Regular expressions - the power of DSLs in Scala  | 
         | 
    79 //                                     and Laziness  | 
         | 
    80 //==================================================  | 
         | 
    81   | 
         | 
    82 abstract class Rexp  | 
         | 
    83 case object ZERO extends Rexp                     // nothing  | 
         | 
    84 case object ONE extends Rexp                      // the empty string  | 
         | 
    85 case class CHAR(c: Char) extends Rexp             // a character c  | 
         | 
    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    | 
         | 
    88 case class STAR(r: Rexp) extends Rexp             // star         r*  | 
         | 
    89   | 
         | 
    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  | 
         | 
    98 import scala.language.implicitConversions      | 
         | 
    99 import scala.language.reflectiveCalls   | 
         | 
   100   | 
         | 
   101 def charlist2rexp(s: List[Char]): Rexp = s match { | 
         | 
   102   case Nil => ONE  | 
         | 
   103   case c::Nil => CHAR(c)  | 
         | 
   104   case c::s => SEQ(CHAR(c), charlist2rexp(s))  | 
         | 
   105 }  | 
         | 
   106 implicit def string2rexp(s: String): Rexp =   | 
         | 
   107   charlist2rexp(s.toList)  | 
         | 
   108   | 
         | 
   109   | 
         | 
   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 { | 
         | 
   115   def | (s: Rexp) = ALT(r, s)  | 
         | 
   116   def % = STAR(r)  | 
         | 
   117   def ~ (s: Rexp) = SEQ(r, s)  | 
         | 
   118 }  | 
         | 
   119   | 
         | 
   120   | 
         | 
   121 implicit def stringOps (s: String) = new { | 
         | 
   122   def | (r: Rexp) = ALT(s, r)  | 
         | 
   123   def | (r: String) = ALT(s, r)  | 
         | 
   124   def % = STAR(s)  | 
         | 
   125   def ~ (r: Rexp) = SEQ(s, r)  | 
         | 
   126   def ~ (r: String) = SEQ(s, r)  | 
         | 
   127 }  | 
         | 
   128   | 
         | 
   129   | 
         | 
   130 def depth(r: Rexp) : Int = r match { | 
         | 
   131   case ZERO => 0  | 
         | 
   132   case ONE => 0  | 
         | 
   133   case CHAR(_) => 0  | 
         | 
   134   case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1  | 
         | 
   135   case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1   | 
         | 
   136   case STAR(r1) => depth(r1) + 1  | 
         | 
   137 }  | 
         | 
   138   | 
         | 
   139 //example regular expressions  | 
         | 
   140 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"  | 
         | 
   141 val sign = "+" | "-" | ""  | 
         | 
   142 val number = sign ~ digit ~ digit.%   | 
         | 
   143   | 
         | 
   144 // task: enumerate exhaustively regular expression  | 
         | 
   145 // starting from small ones towards bigger ones.  | 
         | 
   146   | 
         | 
   147 // 1st idea: enumerate them up to a level  | 
         | 
   148   | 
         | 
   149 def enuml(l: Int, s: String) : Set[Rexp] = l match { | 
         | 
   150   case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet  | 
         | 
   151   case n =>    | 
         | 
   152     val rs = enuml(n - 1, s)  | 
         | 
   153     rs ++  | 
         | 
   154     (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++  | 
         | 
   155     (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++  | 
         | 
   156     (for (r1 <- rs) yield STAR(r1))  | 
         | 
   157 }  | 
         | 
   158   | 
         | 
   159 enuml(1, "a").size  | 
         | 
   160 enuml(2, "a").size  | 
         | 
   161 enuml(3, "a").size // out of heap space  | 
         | 
   162   | 
         | 
   163   | 
         | 
   164 def enum(rs: Stream[Rexp]) : Stream[Rexp] =   | 
         | 
   165   rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #:::  | 
         | 
   166                 (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::  | 
         | 
   167                 (for (r1 <- rs) yield STAR(r1)) )  | 
         | 
   168   | 
         | 
   169   | 
         | 
   170 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200).force  | 
         | 
   171 enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR)).take(200000).force  | 
         | 
   172   | 
         | 
   173   | 
         | 
   174 val is =   | 
         | 
   175   (enum(ZERO #:: ONE #:: "ab".toStream.map(CHAR))  | 
         | 
   176     .dropWhile(depth(_) < 3)  | 
         | 
   177     .take(10).foreach(println))  | 
         | 
   178   | 
         | 
   179   | 
         | 
   180   | 
         | 
   181 // Parsing - The Solved Problem That Isn't  | 
         | 
   182 //=========================================  | 
         | 
   183 //  | 
         | 
   184 // https://tratt.net/laurie/blog/entries/parsing_the_solved_problem_that_isnt.html  | 
         | 
   185 //  | 
         | 
   186 // Or, A topic of endless "fun"(?)  | 
         | 
   187   | 
         | 
   188   | 
         | 
   189 // input type: String  | 
         | 
   190 // output type: Int  | 
         | 
   191 Integer.parseInt("123456") | 
         | 
   192   | 
         | 
   193 /* Note, in the previous lectures I did not show the type consraint  | 
         | 
   194  * I <% Seq[_] , which means that the input type I can be  | 
         | 
   195  * treated, or seen, as a sequence. */  | 
         | 
   196   | 
         | 
   197 abstract class Parser[I <% Seq[_], T] { | 
         | 
   198   def parse(ts: I): Set[(T, I)]  | 
         | 
   199   | 
         | 
   200   def parse_all(ts: I) : Set[T] =  | 
         | 
   201     for ((head, tail) <- parse(ts);   | 
         | 
   202         if (tail.isEmpty)) yield head  | 
         | 
   203 }  | 
         | 
   204   | 
         | 
   205 // the idea is that a parser can parse something  | 
         | 
   206 // from the input and leaves something unparsed => pairs  | 
         | 
   207   | 
         | 
   208 class AltParser[I <% Seq[_], T](  | 
         | 
   209   p: => Parser[I, T],   | 
         | 
   210   q: => Parser[I, T]) extends Parser[I, T] { | 
         | 
   211   | 
         | 
   212   def parse(sb: I) = p.parse(sb) ++ q.parse(sb)     | 
         | 
   213 }  | 
         | 
   214   | 
         | 
   215   | 
         | 
   216 class SeqParser[I <% Seq[_], T, S](  | 
         | 
   217   p: => Parser[I, T],   | 
         | 
   218   q: => Parser[I, S]) extends Parser[I, (T, S)] { | 
         | 
   219   | 
         | 
   220   def parse(sb: I) =   | 
         | 
   221     for ((head1, tail1) <- p.parse(sb);   | 
         | 
   222          (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2)  | 
         | 
   223 }  | 
         | 
   224   | 
         | 
   225   | 
         | 
   226 class FunParser[I <% Seq[_], T, S](  | 
         | 
   227   p: => Parser[I, T],   | 
         | 
   228   f: T => S) extends Parser[I, S] { | 
         | 
   229   | 
         | 
   230   def parse(sb: I) =   | 
         | 
   231     for ((head, tail) <- p.parse(sb)) yield (f(head), tail)  | 
         | 
   232 }  | 
         | 
   233   | 
         | 
   234   | 
         | 
   235 implicit def ParserOps[I<% Seq[_], T](p: Parser[I, T]) = new { | 
         | 
   236   def | (q : => Parser[I, T]) = new AltParser[I, T](p, q)  | 
         | 
   237   def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)  | 
         | 
   238   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)  | 
         | 
   239 }  | 
         | 
   240   | 
         | 
   241 implicit def StringOps(s: String) = new { | 
         | 
   242   def | (q : => Parser[String, String]) = new AltParser[String, String](s, q)  | 
         | 
   243   def | (r: String) = new AltParser[String, String](s, r)  | 
         | 
   244   def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f)  | 
         | 
   245   def ~[S] (q : => Parser[String, S]) =   | 
         | 
   246     new SeqParser[String, String, S](s, q)  | 
         | 
   247   def ~ (r: String) =   | 
         | 
   248     new SeqParser[String, String, String](s, r)  | 
         | 
   249 }  | 
         | 
   250   | 
         | 
   251   | 
         | 
   252 // atomic parsers    | 
         | 
   253 case class CharParser(c: Char) extends Parser[String, Char] { | 
         | 
   254   def parse(sb: String) =   | 
         | 
   255     if (sb != "" && sb.head == c) Set((c, sb.tail)) else Set()  | 
         | 
   256 }  | 
         | 
   257   | 
         | 
   258 import scala.util.matching.Regex  | 
         | 
   259 case class RegexParser(reg: Regex) extends Parser[String, String] { | 
         | 
   260   def parse(sb: String) = reg.findPrefixMatchOf(sb) match { | 
         | 
   261     case None => Set()  | 
         | 
   262     case Some(m) => Set((m.matched, m.after.toString))    | 
         | 
   263   }  | 
         | 
   264 }  | 
         | 
   265   | 
         | 
   266 val NumParser = RegexParser("[0-9]+".r) | 
         | 
   267 def StringParser(s: String) = RegexParser(Regex.quote(s).r)  | 
         | 
   268   | 
         | 
   269 println(NumParser.parse_all("12345")) | 
         | 
   270 println(NumParser.parse_all("12u45")) | 
         | 
   271   | 
         | 
   272   | 
         | 
   273 // convenience  | 
         | 
   274 implicit def string2parser(s: String) = StringParser(s)  | 
         | 
   275 implicit def char2parser(c: Char) = CharParser(c)  | 
         | 
   276   | 
         | 
   277 implicit def ParserOps[I<% Seq[_], T](p: Parser[I, T]) = new { | 
         | 
   278   def | (q : => Parser[I, T]) = new AltParser[I, T](p, q)  | 
         | 
   279   def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)  | 
         | 
   280   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)  | 
         | 
   281 }  | 
         | 
   282   | 
         | 
   283 implicit def StringOps(s: String) = new { | 
         | 
   284   def | (q : => Parser[String, String]) = new AltParser[String, String](s, q)  | 
         | 
   285   def | (r: String) = new AltParser[String, String](s, r)  | 
         | 
   286   def ==>[S] (f: => String => S) = new FunParser[String, String, S](s, f)  | 
         | 
   287   def ~[S] (q : => Parser[String, S]) =   | 
         | 
   288     new SeqParser[String, String, S](s, q)  | 
         | 
   289   def ~ (r: String) =   | 
         | 
   290     new SeqParser[String, String, String](s, r)  | 
         | 
   291 }  | 
         | 
   292   | 
         | 
   293   | 
         | 
   294 val NumParserInt = NumParser ==> (s => s.toInt)  | 
         | 
   295   | 
         | 
   296 NumParser.parse_all("12345") | 
         | 
   297 NumParserInt.parse_all("12345") | 
         | 
   298 NumParserInt.parse_all("12u45") | 
         | 
   299   | 
         | 
   300   | 
         | 
   301 // grammar for arithmetic expressions  | 
         | 
   302 //  | 
         | 
   303 //  E ::= T + E | T - E | T  | 
         | 
   304 //  T ::= F * T | F  | 
         | 
   305 //  F ::= ( E ) | Number  | 
         | 
   306   | 
         | 
   307   | 
         | 
   308 lazy val E: Parser[String, Int] =   | 
         | 
   309   (T ~ "+" ~ E) ==> { case ((x, y), z) => x + z } | | 
         | 
   310   (T ~ "-" ~ E) ==> { case ((x, y), z) => x - z } | T  | 
         | 
   311 lazy val T: Parser[String, Int] =   | 
         | 
   312   (F ~ "*" ~ T) ==> { case ((x, y), z) => x * z } | F | 
         | 
   313 lazy val F: Parser[String, Int] =   | 
         | 
   314   ("(" ~ E ~ ")") ==> { case ((x, y), z) => y } | NumParserInt | 
         | 
   315   | 
         | 
   316 println(E.parse_all("1+3+4")) | 
         | 
   317 println(E.parse_all("4*2+3")) | 
         | 
   318 println(E.parse_all("4*(2+3)")) | 
         | 
   319 println(E.parse_all("(4)*((2+3))")) | 
         | 
   320 println(E.parse_all("4/2+3")) | 
         | 
   321 println(E.parse_all("(1+2)+3")) | 
         | 
   322 println(E.parse_all("1+2+3"))  | 
         | 
   323   | 
         | 
   324   | 
         | 
   325   | 
         | 
   326   | 
         | 
   327   | 
         | 
   328 // The End ... Almost Christimas  | 
         | 
   329 //===============================  | 
         | 
   330   | 
         | 
   331 // I hope you had fun!  | 
         | 
   332   | 
         | 
   333 // A function should do one thing, and only one thing.  | 
         | 
   334   | 
         | 
   335 // Make your variables immutable, unless there's a good   | 
         | 
   336 // reason not to.  | 
         | 
   337   | 
         | 
   338 // I did it, but this is actually not a good reason:  | 
         | 
   339 // generating new labels  | 
         | 
   340 var counter = -1  | 
         | 
   341   | 
         | 
   342 def Fresh(x: String) = { | 
         | 
   343   counter += 1  | 
         | 
   344   x ++ "_" ++ counter.toString()  | 
         | 
   345 }  | 
         | 
   346   | 
         | 
   347 Fresh("x") | 
         | 
   348 Fresh("x") | 
         | 
   349   | 
         | 
   350   | 
         | 
   351   | 
         | 
   352 // You can be productive on Day 1, but the language is deep.  | 
         | 
   353 //  | 
         | 
   354 // http://scalapuzzlers.com  | 
         | 
   355 //  | 
         | 
   356 // http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/  | 
         | 
   357   | 
         | 
   358 List(1, 2, 3) contains "your mom"  | 
         | 
   359   | 
         | 
   360 // I like best about Scala that it lets me often write  | 
         | 
   361 // concise, readable code. And it hooks up with the   | 
         | 
   362 // Isabelle theorem prover.  | 
         | 
   363   |