diff -r 56732dbefcff -r 5e489c9fe47b progs/lecture4.scala --- a/progs/lecture4.scala Fri Nov 30 08:56:22 2018 +0000 +++ b/progs/lecture4.scala Fri Nov 30 13:06:09 2018 +0000 @@ -8,21 +8,6 @@ // You do not want to write functions like contains, first, // length and so on for every type of lists. -List("one", "two", "three", "four") - - - - - - - - - - - - - - def length_string_list(lst: List[String]): Int = lst match { case Nil => 0 @@ -51,7 +36,7 @@ case x::xs => f(x)::map(xs, f) } -map(List(1, 2, 3, 4), (x: Int) => x * x) +map(List(1, 2, 3, 4), (x: Int) => x.toString) // Remember? @@ -63,6 +48,8 @@ val ls = List(1,2,3,3,2,4,3,2,1) ls.distinct +ls.minBy(_._2) +ls.sortBy(_._1) def distinctBy[B, C](xs: List[B], f: B => C, @@ -92,7 +79,7 @@ val x = id(322) // Int val y = id("hey") // String -val z = id(Set(1,2,3,4)) // Set[Int] +val z = id(Set[Int](1,2,3,4)) // Set[Int] @@ -111,7 +98,8 @@ // arr[0] = "Hello World"; -// Scala gives you a compile-time error +// Scala gives you a compile-time error, which +// is much better. var arr = Array[Int]() arr(0) = "Hello World" @@ -119,18 +107,20 @@ - - // // Object Oriented Programming in Scala // // ===================================== abstract class Animal -case class Bird(name: String) extends Animal +case class Bird(name: String) extends Animal { + override def toString = name +} case class Mammal(name: String) extends Animal case class Reptile(name: String) extends Animal +Bird("Sparrow") + println(Bird("Sparrow")) println(Bird("Sparrow").toString) @@ -142,7 +132,7 @@ // There is a very convenient short-hand notation -// for constructors +// for constructors: class Fraction(x: Int, y: Int) { def numer = x @@ -186,7 +176,7 @@ // ...to allow the notation n + m * i import scala.language.implicitConversions -object i extends Complex(0, 1) +val i = Complex(0, 1) implicit def double2complex(re: Double) = Complex(re, 0) @@ -222,6 +212,7 @@ // DFAs in Scala +//=============== import scala.util.Try @@ -348,7 +339,8 @@ // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs? -// A: Subset construction. +// A: Subset construction. Here the state type for the DFA is +// sets of states. def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = { DFA(nfa.starts, @@ -393,21 +385,21 @@ - // Regular expressions - the power of DSLs in Scala //================================================== abstract class Rexp -case object ZERO extends Rexp // nothing -case object ONE extends Rexp // the empty string -case class CHAR(c: Char) extends Rexp // a character c -case class ALT(r1: Rexp, r2: Rexp) extends Rexp // alternative r1 + r2 -case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence r1 . r2 -case class STAR(r: Rexp) extends Rexp // star r* +case object ZERO extends Rexp // nothing +case object ONE extends Rexp // the empty string +case class CHAR(c: Char) extends Rexp // a character c +case class ALT(r1: Rexp, r2: Rexp) extends Rexp // alternative r1 + r2 +case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence r1 . r2 +case class STAR(r: Rexp) extends Rexp // star r* -// (ab)* +// writing (ab)* in the format above is +// tedious val r0 = STAR(SEQ(CHAR('a'), CHAR('b'))) @@ -434,6 +426,7 @@ def ~ (s: Rexp) = SEQ(r, s) } + implicit def stringOps (s: String) = new { def | (r: Rexp) = ALT(s, r) def | (r: String) = ALT(s, r) @@ -452,7 +445,9 @@ // Lazy Evaluation //================= // -// do not evaluate arguments just yet +// Do not evaluate arguments just yet: +// this uses the => in front of the type +// of the code-argument def time_needed[T](i: Int, code: => T) = { val start = System.nanoTime() @@ -468,5 +463,6 @@ ("a" * 10).matches(evil) ("a" * 10000).matches(evil) ("a" * 20000).matches(evil) +("a" * 50000).matches(evil) -time_needed(2, ("a" * 10000).matches(evil)) +time_needed(1, ("a" * 50000).matches(evil))