progs/lecture4.scala
author Christian Urban <urbanc@in.tum.de>
Tue, 19 Nov 2019 06:38:20 +0000
changeset 322 856aaa591840
parent 320 90aed247c8cf
child 325 26058bf089ae
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     1
// Scala Lecture 4
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     2
//=================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     3
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     4
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     5
// Polymorphic Types
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     6
//===================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     7
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     8
// You do not want to write functions like contains, first, 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
     9
// length and so on for every type of lists.
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    10
224
1a45c9bcc77b updated
Christian Urban <urbanc@in.tum.de>
parents: 223
diff changeset
    11
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    12
def length_string_list(lst: List[String]): Int = lst match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    13
  case Nil => 0
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    14
  case x::xs => 1 + length_string_list(xs)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    15
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    16
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    17
def length_int_list(lst: List[Int]): Int = lst match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    18
  case Nil => 0
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    19
  case x::xs => 1 + length_int_list(xs)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    20
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    21
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    22
length_string_list(List("1", "2", "3", "4"))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    23
length_int_list(List(1, 2, 3, 4))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    24
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    25
def length[A](lst: List[A]): Int = lst match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    26
  case Nil => 0
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    27
  case x::xs => 1 + length(xs)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    28
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    29
length(List("1", "2", "3", "4"))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    30
length(List(1, 2, 3, 4))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    31
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    32
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    33
def map[A, B](lst: List[A], f: A => B): List[B] = lst match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    34
  case Nil => Nil
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    35
  case x::xs => f(x)::map(xs, f) 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    36
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    37
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    38
map(List(1, 2, 3, 4), (x: Int) => x.toString)
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    39
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    40
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    41
// Remember?
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    42
def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ...
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    43
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    44
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    45
// distinct / distinctBy
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    46
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    47
val ls = List(1,2,3,3,2,4,3,2,1)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    48
ls.distinct
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    49
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    50
ls.minBy(_._2)
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    51
ls.sortBy(_._1)
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    52
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    53
def distinctBy[B, C](xs: List[B], 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    54
                     f: B => C, 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    55
                     acc: List[C] = Nil): List[B] = xs match {
218
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    56
  case Nil => Nil
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    57
  case x::xs => {
218
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    58
    val res = f(x)
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    59
    if (acc.contains(res)) distinctBy(xs, f, acc)  
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    60
    else x::distinctBy(xs, f, res::acc)
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    61
  }
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    62
} 
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    63
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    64
// distinctBy  with the identity function is 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    65
// just distinct
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    66
distinctBy(ls, (x: Int) => x)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    67
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    68
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    69
val cs = List('A', 'b', 'a', 'c', 'B', 'D', 'd')
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    70
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    71
distinctBy(cs, (c:Char) => c.toUpper)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    72
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    73
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    74
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    75
// Type inference is local in Scala
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    76
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    77
def id[T](x: T) : T = x
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    78
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    79
val x = id(322)          // Int
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    80
val y = id("hey")        // String
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
    81
val z = id(Set[Int](1,2,3,4)) // Set[Int]
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    82
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    83
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    84
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    85
// The type variable concept in Scala can get really complicated.
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    86
//
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    87
// - variance (OO)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    88
// - bounds (subtyping)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    89
// - quantification
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    90
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    91
// Java has issues with this too: Java allows
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    92
// to write the following incorrect code, and
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    93
// only recovers by raising an exception
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    94
// at runtime.
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    95
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    96
// Object[] arr = new Integer[10];
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
    97
// arr[0] = "Hello World";
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    98
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
    99
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   100
// Scala gives you a compile-time error, which
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   101
// is much better.
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   102
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   103
var arr = Array[Int]()
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   104
arr(0) = "Hello World"
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   105
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   106
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   107
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   108
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   109
//
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   110
// Object Oriented Programming in Scala
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   111
//
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   112
// =====================================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   113
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   114
abstract class Animal
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   115
case class Bird(name: String) extends Animal {
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   116
   override def toString = name
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   117
}
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   118
case class Mammal(name: String) extends Animal
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   119
case class Reptile(name: String) extends Animal
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   120
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   121
Bird("Sparrow")
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   122
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   123
println(Bird("Sparrow"))
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   124
println(Bird("Sparrow").toString)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   125
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   126
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   127
// you can override methods
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   128
case class Bird(name: String) extends Animal {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   129
  override def toString = name
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   130
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   131
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   132
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   133
// There is a very convenient short-hand notation
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   134
// for constructors:
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   135
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   136
class Fraction(x: Int, y: Int) {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   137
  def numer = x
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   138
  def denom = y
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   139
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   140
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   141
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   142
case class Fraction(numer: Int, denom: Int)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   143
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   144
val half = Fraction(1, 2)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   145
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   146
half.denom
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   147
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   148
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   149
// In mandelbrot.scala I used complex (imaginary) numbers 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   150
// and implemented the usual arithmetic operations for complex 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   151
// numbers.
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   152
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   153
case class Complex(re: Double, im: Double) { 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   154
  // represents the complex number re + im * i
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   155
  def +(that: Complex) = Complex(this.re + that.re, this.im + that.im)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   156
  def -(that: Complex) = Complex(this.re - that.re, this.im - that.im)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   157
  def *(that: Complex) = Complex(this.re * that.re - this.im * that.im,
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   158
                                 this.re * that.im + that.re * this.im)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   159
  def *(that: Double) = Complex(this.re * that, this.im * that)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   160
  def abs = Math.sqrt(this.re * this.re + this.im * this.im)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   161
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   162
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   163
val test = Complex(1, 2) + Complex (3, 4)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   164
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   165
// this could have equally been written as
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   166
val test = Complex(1, 2).+(Complex (3, 4))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   167
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   168
// this applies to all methods, but requires
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   169
import scala.language.postfixOps
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   170
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   171
List(5, 2, 3, 4).sorted
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   172
List(5, 2, 3, 4) sorted
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   173
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   174
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   175
// ...to allow the notation n + m * i
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   176
import scala.language.implicitConversions   
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   177
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   178
val i = Complex(0, 1)
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   179
implicit def double2complex(re: Double) = Complex(re, 0)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   180
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   181
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   182
val inum1 = -2.0 + -1.5 * i
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   183
val inum2 =  1.0 +  1.5 * i
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   184
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   185
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   186
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   187
// All is public by default....so no public is needed.
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   188
// You can have the usual restrictions about private 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   189
// values and methods, if you are MUTABLE !!!
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   190
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   191
case class BankAccount(init: Int) {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   192
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   193
  private var balance = init
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   194
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   195
  def deposit(amount: Int): Unit = {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   196
    if (amount > 0) balance = balance + amount
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   197
  }
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   198
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   199
  def withdraw(amount: Int): Int =
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   200
    if (0 < amount && amount <= balance) {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   201
      balance = balance - amount
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   202
      balance
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   203
    } else throw new Error("insufficient funds")
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   204
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   205
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   206
// BUT since we are completely IMMUTABLE, this is 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   207
// virtually of not concern to us.
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   208
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   209
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   210
243
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   211
// another example about Fractions
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   212
import scala.language.implicitConversions
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   213
import scala.language.reflectiveCalls
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   214
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   215
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   216
case class Fraction(numer: Int, denom: Int) {
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   217
  override def toString = numer.toString + "/" + denom.toString
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   218
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   219
  def +(other: Fraction) = Fraction(numer + other.numer, denom + other.denom)
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   220
  def /(other: Fraction) = Fraction(numer * other.denom, denom * other.numer)
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   221
  def /% (other: Fraction) = Fraction(numer * other.denom, denom * other.numer)
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   222
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   223
}
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   224
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   225
implicit def Int2Fraction(x: Int) = Fraction(x, 1)
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   226
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   227
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   228
val half = Fraction(1, 2)
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   229
val third = Fraction (1, 3)
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   230
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   231
half + third
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   232
half / third
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   233
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   234
// not sure if one can get this to work
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   235
// properly, since Scala just cannot find out
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   236
// if / is for ints or for Fractions 
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   237
(1 / 3) + half
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   238
(1 / 2) + third
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   239
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   240
// either you have to force the Fraction-type by
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   241
// using a method that is not defined for ints
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   242
(1 /% 3) + half
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   243
(1 /% 2) + third
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   244
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   245
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   246
// ...or explicitly give the type in order to allow
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   247
// Scala to do the conversion to Fractions 
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   248
((1:Fraction) / 3) + half
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   249
(1 / (3: Fraction)) + half
80102fba0a93 updated
Christian Urban <urbanc@in.tum.de>
parents: 242
diff changeset
   250
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   251
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   252
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   253
// DFAs in Scala  
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   254
//===============
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   255
import scala.util.Try
218
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   256
ae788eeea8a0 updated
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   257
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   258
// A is the state type
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   259
// C is the input (usually characters)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   260
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   261
case class DFA[A, C](start: A,              // starting state
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   262
                     delta: (A, C) => A,    // transition function
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   263
                     fins:  A => Boolean) { // final states (Set)
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   264
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   265
  def deltas(q: A, s: List[C]) : A = s match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   266
    case Nil => q
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   267
    case c::cs => deltas(delta(q, c), cs)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   268
  }
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   269
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   270
  def accepts(s: List[C]) : Boolean = 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   271
    Try(fins(deltas(start, s))) getOrElse false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   272
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   273
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   274
// the example shown in the handout 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   275
abstract class State
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   276
case object Q0 extends State
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   277
case object Q1 extends State
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   278
case object Q2 extends State
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   279
case object Q3 extends State
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   280
case object Q4 extends State
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   281
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   282
val delta : (State, Char) => State = 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   283
  { case (Q0, 'a') => Q1
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   284
    case (Q0, 'b') => Q2
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   285
    case (Q1, 'a') => Q4
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   286
    case (Q1, 'b') => Q2
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   287
    case (Q2, 'a') => Q3
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   288
    case (Q2, 'b') => Q2
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   289
    case (Q3, 'a') => Q4
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   290
    case (Q3, 'b') => Q0
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   291
    case (Q4, 'a') => Q4
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   292
    case (Q4, 'b') => Q4 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   293
    case _ => throw new Exception("Undefined") }
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   294
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   295
val dfa = DFA(Q0, delta, Set[State](Q4))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   296
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   297
dfa.accepts("abaaa".toList)     // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   298
dfa.accepts("bbabaab".toList)   // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   299
dfa.accepts("baba".toList)      // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   300
dfa.accepts("abc".toList)       // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   301
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   302
// another DFA with a Sink state
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   303
abstract class S
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   304
case object S0 extends S
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   305
case object S1 extends S
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   306
case object S2 extends S
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   307
case object Sink extends S
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   308
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   309
// transition function with a sink state
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   310
val sigma : (S, Char) => S = 
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   311
  { case (S0, 'a') => S1
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   312
    case (S1, 'a') => S2
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   313
    case _ => Sink
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   314
  }
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   315
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   316
val dfa2 = DFA(S0, sigma, Set[S](S2))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   317
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   318
dfa2.accepts("aa".toList)        // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   319
dfa2.accepts("".toList)          // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   320
dfa2.accepts("ab".toList)        // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   321
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   322
//  we could also have a dfa for numbers
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   323
val sigmai : (S, Int) => S = 
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   324
  { case (S0, 1) => S1
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   325
    case (S1, 1) => S2
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   326
    case _ => Sink
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   327
  }
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   328
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   329
val dfa3 = DFA(S0, sigmai, Set[S](S2))
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   330
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   331
dfa3.accepts(List(1, 1))        // true
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   332
dfa3.accepts(Nil)               // false
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   333
dfa3.accepts(List(1, 2))        // false
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   334
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   335
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   336
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   337
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   338
// NFAs (Nondeterministic Finite Automata)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   339
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   340
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   341
case class NFA[A, C](starts: Set[A],          // starting states
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   342
                     delta: (A, C) => Set[A], // transition function
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   343
                     fins:  A => Boolean) {   // final states 
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   344
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   345
  // given a state and a character, what is the set of 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   346
  // next states? if there is none => empty set
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   347
  def next(q: A, c: C) : Set[A] = 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   348
    Try(delta(q, c)) getOrElse Set[A]() 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   349
242
3308eeb73d11 updated
Christian Urban <urbanc@in.tum.de>
parents: 226
diff changeset
   350
  def nexts(qs: Set[A], c: C) : Set[A] =
3308eeb73d11 updated
Christian Urban <urbanc@in.tum.de>
parents: 226
diff changeset
   351
    qs.flatMap(next(_, c))
3308eeb73d11 updated
Christian Urban <urbanc@in.tum.de>
parents: 226
diff changeset
   352
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   353
  // depth-first version of accepts
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   354
  def search(q: A, s: List[C]) : Boolean = s match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   355
    case Nil => fins(q)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   356
    case c::cs => next(q, c).exists(search(_, cs))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   357
  }
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   358
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   359
  def accepts(s: List[C]) : Boolean =
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   360
    starts.exists(search(_, s))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   361
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   362
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   363
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   364
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   365
// NFA examples
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   366
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   367
val nfa_trans1 : (State, Char) => Set[State] = 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   368
  { case (Q0, 'a') => Set(Q0, Q1) 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   369
    case (Q0, 'b') => Set(Q2) 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   370
    case (Q1, 'a') => Set(Q1) 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   371
    case (Q2, 'b') => Set(Q2) }
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   372
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   373
val nfa = NFA(Set[State](Q0), nfa_trans1, Set[State](Q2))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   374
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   375
nfa.accepts("aa".toList)             // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   376
nfa.accepts("aaaaa".toList)          // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   377
nfa.accepts("aaaaab".toList)         // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   378
nfa.accepts("aaaaabbb".toList)       // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   379
nfa.accepts("aaaaabbbaaa".toList)    // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   380
nfa.accepts("ac".toList)             // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   381
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   382
223
417df5986615 updated
Christian Urban <urbanc@in.tum.de>
parents: 222
diff changeset
   383
// Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   384
// A: Subset construction. Here the state type for the DFA is
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   385
//    sets of states.
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   386
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   387
def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   388
  DFA(nfa.starts, 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   389
      { case (qs, c) => nfa.nexts(qs, c) }, 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   390
      _.exists(nfa.fins))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   391
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   392
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   393
subset(nfa1).accepts("aa".toList)             // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   394
subset(nfa1).accepts("aaaaa".toList)          // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   395
subset(nfa1).accepts("aaaaab".toList)         // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   396
subset(nfa1).accepts("aaaaabbb".toList)       // true
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   397
subset(nfa1).accepts("aaaaabbbaaa".toList)    // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   398
subset(nfa1).accepts("ac".toList)             // false
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   399
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   400
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   401
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   402
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   403
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   404
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   405
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   406
// Cool Stuff in Scala
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   407
//=====================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   408
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   409
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   410
// Implicits or How to Pimp my Library
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   411
//=====================================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   412
//
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   413
// For example adding your own methods to Strings:
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   414
// Imagine you want to increment strings, like
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   415
//
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   416
//     "HAL".increment
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   417
//
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   418
// you can avoid ugly fudges, like a MyString, by
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   419
// using implicit conversions.
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   420
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   421
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   422
implicit class MyString(s: String) {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   423
  def increment = for (c <- s) yield (c + 1).toChar 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   424
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   425
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   426
"HAL".increment
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   427
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   428
278
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   429
// Abstract idea:
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   430
// In that version implicit conversions were used to solve the 
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   431
// late extension problem; namely, given a class C and a class T, 
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   432
// how to have C extend T without touching or recompiling C. 
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   433
// Conversions add a wrapper when a member of T is requested 
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   434
// from an instance of C.
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   435
319
ed7543c5d317 updated
Christian Urban <urbanc@in.tum.de>
parents: 278
diff changeset
   436
//Another example (TimeUnit in 2.13?)
278
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   437
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   438
case class Duration(time: Long, unit: TimeUnit) {
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   439
  def +(o: Duration) = Duration(time + unit.convert(o.time, o.unit), unit)
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   440
}
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   441
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   442
implicit class Int2Duration(that: Int) {
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   443
  def seconds = new Duration(that, SECONDS)
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   444
  def minutes = new Duration(that, MINUTES)
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   445
}
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   446
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   447
5.seconds + 2.minutes //Duration(125L, SECONDS )
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   448
57b5bba67467 updated
Christian Urban <urbanc@in.tum.de>
parents: 243
diff changeset
   449
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   450
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   451
// Regular expressions - the power of DSLs in Scala
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   452
//==================================================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   453
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   454
abstract class Rexp
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   455
case object ZERO extends Rexp                     // nothing
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   456
case object ONE extends Rexp                      // the empty string
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   457
case class CHAR(c: Char) extends Rexp             // a character c
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   458
case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   459
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   460
case class STAR(r: Rexp) extends Rexp             // star         r*
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   461
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   462
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   463
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   464
// writing (ab)* in the format above is 
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   465
// tedious
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   466
val r0 = STAR(SEQ(CHAR('a'), CHAR('b')))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   467
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   468
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   469
// some convenience for typing in regular expressions
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   470
import scala.language.implicitConversions    
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   471
import scala.language.reflectiveCalls 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   472
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   473
def charlist2rexp(s: List[Char]): Rexp = s match {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   474
  case Nil => ONE
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   475
  case c::Nil => CHAR(c)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   476
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   477
}
224
1a45c9bcc77b updated
Christian Urban <urbanc@in.tum.de>
parents: 223
diff changeset
   478
implicit def string2rexp(s: String): Rexp = 
1a45c9bcc77b updated
Christian Urban <urbanc@in.tum.de>
parents: 223
diff changeset
   479
  charlist2rexp(s.toList)
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   480
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   481
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   482
val r1 = STAR("ab")
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   483
val r2 = STAR(ALT("ab", "baa baa black sheep"))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   484
val r3 = STAR(SEQ("ab", ALT("a", "b")))
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   485
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   486
implicit def RexpOps (r: Rexp) = new {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   487
  def | (s: Rexp) = ALT(r, s)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   488
  def % = STAR(r)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   489
  def ~ (s: Rexp) = SEQ(r, s)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   490
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   491
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   492
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   493
implicit def stringOps (s: String) = new {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   494
  def | (r: Rexp) = ALT(s, r)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   495
  def | (r: String) = ALT(s, r)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   496
  def % = STAR(s)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   497
  def ~ (r: Rexp) = SEQ(s, r)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   498
  def ~ (r: String) = SEQ(s, r)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   499
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   500
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   501
//example regular expressions
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   502
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   503
val sign = "+" | "-" | ""
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   504
val number = sign ~ digit ~ digit.% 
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   505
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   506
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   507
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   508
// Lazy Evaluation
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   509
//=================
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   510
//
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   511
// Do not evaluate arguments just yet:
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   512
// this uses the => in front of the type
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   513
// of the code-argument
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   514
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   515
def time_needed[T](i: Int, code: => T) = {
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   516
  val start = System.nanoTime()
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   517
  for (j <- 1 to i) code
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   518
  val end = System.nanoTime()
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   519
  (end - start)/(i * 1.0e9)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   520
}
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   521
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   522
// same examples using the internal regexes
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   523
val evil = "(a*)*b"
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   524
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   525
("a" * 10 ++ "b").matches(evil)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   526
("a" * 10).matches(evil)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   527
("a" * 10000).matches(evil)
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   528
("a" * 20000).matches(evil)
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   529
("a" * 50000).matches(evil)
222
ec9cbf969edf updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   530
226
6bb7810d2108 updated
Christian Urban <urbanc@in.tum.de>
parents: 225
diff changeset
   531
time_needed(1, ("a" * 50000).matches(evil))