progs/lecture4.scala
changeset 226 5e489c9fe47b
parent 225 56732dbefcff
child 242 e6b34f617915
equal deleted inserted replaced
225:56732dbefcff 226:5e489c9fe47b
     5 // Polymorphic Types
     5 // Polymorphic Types
     6 //===================
     6 //===================
     7 
     7 
     8 // You do not want to write functions like contains, first, 
     8 // You do not want to write functions like contains, first, 
     9 // length and so on for every type of lists.
     9 // length and so on for every type of lists.
    10 
       
    11 List("one", "two", "three", "four")
       
    12 
       
    13 
       
    14 
       
    15 
       
    16 
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 
    10 
    26 
    11 
    27 def length_string_list(lst: List[String]): Int = lst match {
    12 def length_string_list(lst: List[String]): Int = lst match {
    28   case Nil => 0
    13   case Nil => 0
    29   case x::xs => 1 + length_string_list(xs)
    14   case x::xs => 1 + length_string_list(xs)
    49 def map[A, B](lst: List[A], f: A => B): List[B] = lst match {
    34 def map[A, B](lst: List[A], f: A => B): List[B] = lst match {
    50   case Nil => Nil
    35   case Nil => Nil
    51   case x::xs => f(x)::map(xs, f) 
    36   case x::xs => f(x)::map(xs, f) 
    52 }
    37 }
    53 
    38 
    54 map(List(1, 2, 3, 4), (x: Int) => x * x)
    39 map(List(1, 2, 3, 4), (x: Int) => x.toString)
    55 
    40 
    56 
    41 
    57 // Remember?
    42 // Remember?
    58 def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ...
    43 def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ...
    59 
    44 
    61 // distinct / distinctBy
    46 // distinct / distinctBy
    62 
    47 
    63 val ls = List(1,2,3,3,2,4,3,2,1)
    48 val ls = List(1,2,3,3,2,4,3,2,1)
    64 ls.distinct
    49 ls.distinct
    65 
    50 
       
    51 ls.minBy(_._2)
       
    52 ls.sortBy(_._1)
    66 
    53 
    67 def distinctBy[B, C](xs: List[B], 
    54 def distinctBy[B, C](xs: List[B], 
    68                      f: B => C, 
    55                      f: B => C, 
    69                      acc: List[C] = Nil): List[B] = xs match {
    56                      acc: List[C] = Nil): List[B] = xs match {
    70   case Nil => Nil
    57   case Nil => Nil
    90 
    77 
    91 def id[T](x: T) : T = x
    78 def id[T](x: T) : T = x
    92 
    79 
    93 val x = id(322)          // Int
    80 val x = id(322)          // Int
    94 val y = id("hey")        // String
    81 val y = id("hey")        // String
    95 val z = id(Set(1,2,3,4)) // Set[Int]
    82 val z = id(Set[Int](1,2,3,4)) // Set[Int]
    96 
    83 
    97 
    84 
    98 
    85 
    99 // The type variable concept in Scala can get really complicated.
    86 // The type variable concept in Scala can get really complicated.
   100 //
    87 //
   109 
    96 
   110 // Object[] arr = new Integer[10];
    97 // Object[] arr = new Integer[10];
   111 // arr[0] = "Hello World";
    98 // arr[0] = "Hello World";
   112 
    99 
   113 
   100 
   114 // Scala gives you a compile-time error
   101 // Scala gives you a compile-time error, which
       
   102 // is much better.
   115 
   103 
   116 var arr = Array[Int]()
   104 var arr = Array[Int]()
   117 arr(0) = "Hello World"
   105 arr(0) = "Hello World"
   118 
   106 
   119 
   107 
   120 
   108 
   121 
   109 
   122 
       
   123 
       
   124 //
   110 //
   125 // Object Oriented Programming in Scala
   111 // Object Oriented Programming in Scala
   126 //
   112 //
   127 // =====================================
   113 // =====================================
   128 
   114 
   129 abstract class Animal
   115 abstract class Animal
   130 case class Bird(name: String) extends Animal
   116 case class Bird(name: String) extends Animal {
       
   117    override def toString = name
       
   118 }
   131 case class Mammal(name: String) extends Animal
   119 case class Mammal(name: String) extends Animal
   132 case class Reptile(name: String) extends Animal
   120 case class Reptile(name: String) extends Animal
       
   121 
       
   122 Bird("Sparrow")
   133 
   123 
   134 println(Bird("Sparrow"))
   124 println(Bird("Sparrow"))
   135 println(Bird("Sparrow").toString)
   125 println(Bird("Sparrow").toString)
   136 
   126 
   137 
   127 
   140   override def toString = name
   130   override def toString = name
   141 }
   131 }
   142 
   132 
   143 
   133 
   144 // There is a very convenient short-hand notation
   134 // There is a very convenient short-hand notation
   145 // for constructors
   135 // for constructors:
   146 
   136 
   147 class Fraction(x: Int, y: Int) {
   137 class Fraction(x: Int, y: Int) {
   148   def numer = x
   138   def numer = x
   149   def denom = y
   139   def denom = y
   150 }
   140 }
   184 
   174 
   185 
   175 
   186 // ...to allow the notation n + m * i
   176 // ...to allow the notation n + m * i
   187 import scala.language.implicitConversions   
   177 import scala.language.implicitConversions   
   188 
   178 
   189 object i extends Complex(0, 1)
   179 val i = Complex(0, 1)
   190 implicit def double2complex(re: Double) = Complex(re, 0)
   180 implicit def double2complex(re: Double) = Complex(re, 0)
   191 
   181 
   192 
   182 
   193 val inum1 = -2.0 + -1.5 * i
   183 val inum1 = -2.0 + -1.5 * i
   194 val inum2 =  1.0 +  1.5 * i
   184 val inum2 =  1.0 +  1.5 * i
   220 
   210 
   221 
   211 
   222 
   212 
   223 
   213 
   224 // DFAs in Scala  
   214 // DFAs in Scala  
       
   215 //===============
   225 import scala.util.Try
   216 import scala.util.Try
   226 
   217 
   227 
   218 
   228 // A is the state type
   219 // A is the state type
   229 // C is the input (usually characters)
   220 // C is the input (usually characters)
   346 nfa.accepts("aaaaabbbaaa".toList)    // false
   337 nfa.accepts("aaaaabbbaaa".toList)    // false
   347 nfa.accepts("ac".toList)             // false
   338 nfa.accepts("ac".toList)             // false
   348 
   339 
   349 
   340 
   350 // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
   341 // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
   351 // A: Subset construction.
   342 // A: Subset construction. Here the state type for the DFA is
       
   343 //    sets of states.
   352 
   344 
   353 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
   345 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
   354   DFA(nfa.starts, 
   346   DFA(nfa.starts, 
   355       { case (qs, c) => nfa.nexts(qs, c) }, 
   347       { case (qs, c) => nfa.nexts(qs, c) }, 
   356       _.exists(nfa.fins))
   348       _.exists(nfa.fins))
   391 
   383 
   392 "HAL".increment
   384 "HAL".increment
   393 
   385 
   394 
   386 
   395 
   387 
   396 
       
   397 // Regular expressions - the power of DSLs in Scala
   388 // Regular expressions - the power of DSLs in Scala
   398 //==================================================
   389 //==================================================
   399 
   390 
   400 abstract class Rexp
   391 abstract class Rexp
   401 case object ZERO extends Rexp                       // nothing
   392 case object ZERO extends Rexp                     // nothing
   402 case object ONE extends Rexp                        // the empty string
   393 case object ONE extends Rexp                      // the empty string
   403 case class CHAR(c: Char) extends Rexp               // a character c
   394 case class CHAR(c: Char) extends Rexp             // a character c
   404 case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2
   395 case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
   405 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 . r2  
   396 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
   406 case class STAR(r: Rexp) extends Rexp               // star         r*
   397 case class STAR(r: Rexp) extends Rexp             // star         r*
   407 
   398 
   408 
   399 
   409 
   400 
   410 // (ab)*
   401 // writing (ab)* in the format above is 
       
   402 // tedious
   411 val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
   403 val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
   412 
   404 
   413 
   405 
   414 // some convenience for typing in regular expressions
   406 // some convenience for typing in regular expressions
   415 import scala.language.implicitConversions    
   407 import scala.language.implicitConversions    
   431 implicit def RexpOps (r: Rexp) = new {
   423 implicit def RexpOps (r: Rexp) = new {
   432   def | (s: Rexp) = ALT(r, s)
   424   def | (s: Rexp) = ALT(r, s)
   433   def % = STAR(r)
   425   def % = STAR(r)
   434   def ~ (s: Rexp) = SEQ(r, s)
   426   def ~ (s: Rexp) = SEQ(r, s)
   435 }
   427 }
       
   428 
   436 
   429 
   437 implicit def stringOps (s: String) = new {
   430 implicit def stringOps (s: String) = new {
   438   def | (r: Rexp) = ALT(s, r)
   431   def | (r: Rexp) = ALT(s, r)
   439   def | (r: String) = ALT(s, r)
   432   def | (r: String) = ALT(s, r)
   440   def % = STAR(s)
   433   def % = STAR(s)
   450 
   443 
   451 
   444 
   452 // Lazy Evaluation
   445 // Lazy Evaluation
   453 //=================
   446 //=================
   454 //
   447 //
   455 // do not evaluate arguments just yet
   448 // Do not evaluate arguments just yet:
       
   449 // this uses the => in front of the type
       
   450 // of the code-argument
   456 
   451 
   457 def time_needed[T](i: Int, code: => T) = {
   452 def time_needed[T](i: Int, code: => T) = {
   458   val start = System.nanoTime()
   453   val start = System.nanoTime()
   459   for (j <- 1 to i) code
   454   for (j <- 1 to i) code
   460   val end = System.nanoTime()
   455   val end = System.nanoTime()
   466 
   461 
   467 ("a" * 10 ++ "b").matches(evil)
   462 ("a" * 10 ++ "b").matches(evil)
   468 ("a" * 10).matches(evil)
   463 ("a" * 10).matches(evil)
   469 ("a" * 10000).matches(evil)
   464 ("a" * 10000).matches(evil)
   470 ("a" * 20000).matches(evil)
   465 ("a" * 20000).matches(evil)
   471 
   466 ("a" * 50000).matches(evil)
   472 time_needed(2, ("a" * 10000).matches(evil))
   467 
       
   468 time_needed(1, ("a" * 50000).matches(evil))