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