progs/lecture5.scala
changeset 383 c02929f2647c
parent 380 d19b0a50ceb9
child 384 6e1237691307
equal deleted inserted replaced
382:1bd800376e0c 383:c02929f2647c
     1 // Scala Lecture 5
     1 // Scala Lecture 5
     2 //=================
     2 //=================
     3 
     3 
     4 // TODO: word count for a very large file (40GB or so)
       
     5 // Transform Farenheit into Celsius
       
     6 
     4 
     7 
     5 
     8 // Laziness with style
     6 // Laziness with style
     9 //=====================
     7 //=====================
    10 
     8 
   172 
   170 
   173 
   171 
   174 
   172 
   175 // (Immutable)
   173 // (Immutable)
   176 // Object Oriented Programming in Scala
   174 // Object Oriented Programming in Scala
   177 //
       
   178 // =====================================
   175 // =====================================
   179 
   176 
   180 
   177 
   181 abstract class Animal 
   178 abstract class Animal 
   182 case class Bird(name: String) extends Animal {
   179 case class Bird(name: String) extends Animal {
   192 
   189 
   193 Bird("Sparrow")
   190 Bird("Sparrow")
   194 println(Bird("Sparrow"))
   191 println(Bird("Sparrow"))
   195 println(Bird("Sparrow").toString)
   192 println(Bird("Sparrow").toString)
   196 
   193 
       
   194 Bird("Sparrow").copy(name = "House Sparrow")
       
   195 
       
   196 def group(a : Animal) = a match {
       
   197   case Bird(_) => "It's a bird"
       
   198   case Mammal(_) => "It's a mammal"
       
   199 }
       
   200 
   197 
   201 
   198 // There is a very convenient short-hand notation
   202 // There is a very convenient short-hand notation
   199 // for constructors:
   203 // for constructors:
   200 
   204 
   201 class Fraction(x: Int, y: Int) {
   205 class Fraction(x: Int, y: Int) {
   202   def numer = x
   206   def numer = x
   203   def denom = y
   207   def denom = y
   204 }
   208 }
   205 
   209 
   206 val half = new Fraction(1, 2)
   210 val half = new Fraction(1, 2)
       
   211 half.numer
   207 
   212 
   208 case class Fraction(numer: Int, denom: Int)
   213 case class Fraction(numer: Int, denom: Int)
   209 
   214 
   210 val half = Fraction(1, 2)
   215 val half = Fraction(1, 2)
   211 
   216 
       
   217 half.numer
   212 half.denom
   218 half.denom
   213 
   219 
   214 
   220 
   215 // In mandelbrot.scala I used complex (imaginary) numbers 
   221 // In mandelbrot.scala I used complex (imaginary) numbers 
   216 // and implemented the usual arithmetic operations for complex 
   222 // and implemented the usual arithmetic operations for complex 
   226   def abs = Math.sqrt(this.re * this.re + this.im * this.im)
   232   def abs = Math.sqrt(this.re * this.re + this.im * this.im)
   227 }
   233 }
   228 
   234 
   229 val test = Complex(1, 2) + Complex (3, 4)
   235 val test = Complex(1, 2) + Complex (3, 4)
   230 
   236 
       
   237 import scala.language.postfixOps
       
   238 List(5,4,3,2,1).sorted.reverse
       
   239 
   231 // this could have equally been written as
   240 // this could have equally been written as
   232 val test = Complex(1, 2).+(Complex (3, 4))
   241 val test = Complex(1, 2).+(Complex (3, 4))
   233 
   242 
   234 // this applies to all methods, but requires
   243 // this applies to all methods, but requires
   235 import scala.language.postfixOps
   244 import scala.language.postfixOps
   268       balance
   277       balance
   269     } else throw new Error("insufficient funds")
   278     } else throw new Error("insufficient funds")
   270 }
   279 }
   271 
   280 
   272 // BUT since we are completely IMMUTABLE, this is 
   281 // BUT since we are completely IMMUTABLE, this is 
   273 // virtually of not concern to us.
   282 // virtually of no concern to us.
   274 
   283 
   275 
   284 
   276 
   285 
   277 // another example about Fractions
   286 // another example about Fractions
   278 import scala.language.implicitConversions
   287 import scala.language.implicitConversions
   279 import scala.language.reflectiveCalls
   288 import scala.language.reflectiveCalls
   280 
   289 
   281 
       
   282 case class Fraction(numer: Int, denom: Int) {
   290 case class Fraction(numer: Int, denom: Int) {
   283   override def toString = numer.toString + "/" + denom.toString
   291   override def toString = numer.toString + "/" + denom.toString
   284 
   292 
   285   def +(other: Fraction) = Fraction(numer + other.numer, denom + other.denom)
   293   def +(other: Fraction) = 
   286   def /(other: Fraction) = Fraction(numer * other.denom, denom * other.numer)
   294     Fraction(numer * other.denom + other.numer * denom, 
       
   295              denom * other.denom)
       
   296   def *(other: Fraction) = Fraction(numer * other.numer, denom * other.denom)
   287  }
   297  }
   288 
   298 
   289 implicit def Int2Fraction(x: Int) = Fraction(x, 1)
   299 implicit def Int2Fraction(x: Int) = Fraction(x, 1)
   290 
       
   291 
   300 
   292 val half = Fraction(1, 2)
   301 val half = Fraction(1, 2)
   293 val third = Fraction (1, 3)
   302 val third = Fraction (1, 3)
   294 
   303 
   295 half + third
   304 half + third
   296 half / third
   305 half * third
   297 
   306 
   298 (1 / 3) + half
   307 1 + half
   299 (1 / 2) + third
   308 
       
   309 
   300 
   310 
   301 
   311 
   302 // DFAs in Scala  
   312 // DFAs in Scala  
   303 //===============
   313 //===============
   304 import scala.util.Try
   314 import scala.util.Try
   315     case Nil => q
   325     case Nil => q
   316     case c::cs => deltas(delta(q, c), cs)
   326     case c::cs => deltas(delta(q, c), cs)
   317   }
   327   }
   318 
   328 
   319   def accepts(s: List[C]) : Boolean = 
   329   def accepts(s: List[C]) : Boolean = 
   320     Try(fins(deltas(start, s))) getOrElse false
   330     Try(fins(deltas(start, s))).getOrElse(false)
   321 }
   331 }
   322 
   332 
   323 // the example shown in the handout 
   333 // the example shown in the handout 
   324 abstract class State
   334 abstract class State
   325 case object Q0 extends State
   335 case object Q0 extends State
   357                      fins:  A => Boolean) {   // final states 
   367                      fins:  A => Boolean) {   // final states 
   358 
   368 
   359   // given a state and a character, what is the set of 
   369   // given a state and a character, what is the set of 
   360   // next states? if there is none => empty set
   370   // next states? if there is none => empty set
   361   def next(q: A, c: C) : Set[A] = 
   371   def next(q: A, c: C) : Set[A] = 
   362     Try(delta(q, c)) getOrElse Set[A]() 
   372     Try(delta(q, c)).getOrElse(Set[A]()) 
   363 
   373 
   364   def nexts(qs: Set[A], c: C) : Set[A] =
   374   def nexts(qs: Set[A], c: C) : Set[A] =
   365     qs.flatMap(next(_, c))
   375     qs.flatMap(next(_, c))
   366 
   376 
   367   // depth-first version of accepts
   377   // depth-first version of accepts
   395 
   405 
   396 
   406 
   397 // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
   407 // Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
   398 // A: Subset construction. Here the state type for the DFA is
   408 // A: Subset construction. Here the state type for the DFA is
   399 //    sets of states.
   409 //    sets of states.
       
   410 
   400 
   411 
   401 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
   412 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
   402   DFA(nfa.starts, 
   413   DFA(nfa.starts, 
   403       { case (qs, c) => nfa.nexts(qs, c) }, 
   414       { case (qs, c) => nfa.nexts(qs, c) }, 
   404       _.exists(nfa.fins))
   415       _.exists(nfa.fins))