progs/lecture5.scala
author Christian Urban <christian.urban@kcl.ac.uk>
Fri, 26 Apr 2024 17:36:41 +0100
changeset 487 efad9725dfd8
parent 482 769bda18a43d
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
238
046f37a262d0 updated
updated
parents: 226
diff changeset
     1
// Scala Lecture 5
222
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
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
     4
for (n <- (1 to 10).toList) yield {
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
     5
  val add = 10
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
     6
  n + add
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
     7
}
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
     8
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
     9
println(add)
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    10
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    11
List(1,2,3,4).sum
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    12
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    13
// extension methods
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    14
// implicit conversions
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    15
// (Immutable) OOP
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    16
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    17
// Cool Stuff in Scala
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    18
//=====================
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    19
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    20
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    21
// Extensions or How to Pimp your Library
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    22
//======================================
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    23
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    24
// For example adding your own methods to Strings:
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    25
// Imagine you want to increment strings, like
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    26
//
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    27
//     "HAL".increment
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    28
//
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    29
// you can avoid ugly fudges, like a MyString, by
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    30
// using extensions.
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    31
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    32
extension (s: String) {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    33
  def increment = s.map(c => (c + 1).toChar)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    34
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    35
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    36
"HAL".increment
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    37
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    38
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    39
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    40
// a more relevant example
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    41
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    42
import scala.concurrent.duration.{TimeUnit,SECONDS,MINUTES}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    43
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    44
case class Duration(time: Long, unit: TimeUnit) {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    45
  def +(o: Duration) = 
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    46
    Duration(time + unit.convert(o.time, o.unit), unit)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    47
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    48
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    49
extension (that: Int) {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    50
  def seconds = Duration(that, SECONDS)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    51
  def minutes = Duration(that, MINUTES)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    52
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    53
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    54
2.minutes + 60.seconds
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    55
5.seconds + 2.minutes   //Duration(125, SECONDS )
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    56
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    57
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    58
// Implicit Conversions
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    59
//=====================
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    60
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    61
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    62
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    63
// Regular expressions - the power of DSLs in Scala
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    64
//==================================================
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    65
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    66
abstract class Rexp
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    67
case object ZERO extends Rexp                     // nothing
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    68
case object ONE extends Rexp                      // the empty string
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    69
case class CHAR(c: Char) extends Rexp             // a character c
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    70
case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    71
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    72
case class STAR(r: Rexp) extends Rexp             // star         r*
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    73
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    74
val r = STAR(CHAR('a'))
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    75
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    76
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    77
// some convenience for typing in regular expressions
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    78
import scala.language.implicitConversions    
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    79
import scala.language.reflectiveCalls 
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    80
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    81
def charlist2rexp(s: List[Char]): Rexp = s match {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    82
  case Nil => ONE
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    83
  case c::Nil => CHAR(c)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    84
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    85
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    86
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    87
given Conversion[String, Rexp] = (s => charlist2rexp(s.toList))
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    88
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    89
extension (r: Rexp) {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    90
  def | (s: Rexp) = ALT(r, s)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    91
  def % = STAR(r)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    92
  def ~ (s: Rexp) = SEQ(r, s)
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    93
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    94
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    95
val r1 = CHAR('a') | CHAR('b') | CHAR('c')
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    96
val r2 = CHAR('a') ~  CHAR('b')
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
    97
482
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    98
val r3 : Rexp = "hello world"
769bda18a43d updated jars
Christian Urban <christian.urban@kcl.ac.uk>
parents: 481
diff changeset
    99
      
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   100
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   101
//example regular expressions
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   102
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   103
val sign = "+" | "-" | ""
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   104
val number = sign ~ digit ~ digit.% 
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   105
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   106
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   107
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   108
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   109
// Object Oriented Programming in Scala
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   110
// =====================================
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   111
329
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   112
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   113
abstract class Animal 
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   114
case class Bird(name: String) extends Animal {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   115
   override def toString = name
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   116
}
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   117
case class Mammal(name: String) extends Animal
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   118
case class Reptile(name: String) extends Animal
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   119
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   120
Mammal("Zebra")
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   121
println(Mammal("Zebra"))
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   122
println(Mammal("Zebra").toString)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   123
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   124
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   125
Bird("Sparrow")
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   126
println(Bird("Sparrow"))
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   127
println(Bird("Sparrow").toString)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   128
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   129
Bird("Sparrow").copy(name = "House Sparrow")
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   130
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   131
def group(a : Animal) = a match {
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   132
  case Bird(_) => "It's a bird"
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   133
  case Mammal(_) => "It's a mammal"
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   134
}
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   135
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   136
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   137
// There is a very convenient short-hand notation
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   138
// for constructors:
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   139
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   140
class Fraction(x: Int, y: Int) {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   141
  def numer = x
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   142
  def denom = y
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   143
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   144
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   145
val half = Fraction(1, 2)
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   146
half.numer
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   147
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   148
// does not work with "vanilla" classes
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   149
half match {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   150
  case Fraction(x, y) => x / y
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   151
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   152
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   153
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   154
case class Fraction(numer: Int, denom: Int)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   155
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   156
val half = Fraction(1, 2)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   157
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   158
half.numer
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   159
half.denom
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   160
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   161
// works with case classes
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   162
half match {
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   163
  case Fraction(x, y) => x / y
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   164
}
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   165
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   166
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   167
// In mandelbrot.scala I used complex (imaginary) numbers 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   168
// and implemented the usual arithmetic operations for complex 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   169
// numbers.
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   170
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   171
case class Complex(re: Double, im: Double) { 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   172
  // represents the complex number re + im * i
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   173
  def +(that: Complex) = Complex(this.re + that.re, this.im + that.im)
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   174
  def -(that: Complex) = Complex(this.re - that.re, this.im - that.im)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   175
  def *(that: Complex) = Complex(this.re * that.re - this.im * that.im,
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   176
                                 this.re * that.im + that.re * this.im)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   177
  def *(that: Double) = Complex(this.re * that, this.im * that)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   178
  def abs = Math.sqrt(this.re * this.re + this.im * this.im)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   179
}
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   180
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   181
// usual way to reference methods
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   182
//object.method(....)
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   183
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   184
val test = Complex(1, 2) + (Complex (3, 4))
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   185
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   186
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   187
import scala.language.postfixOps
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   188
(List(5,4,3,2,1) sorted) reverse
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   189
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   190
// this could have equally been written as
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   191
val test = Complex(1, 2).+(Complex (3, 4))
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   192
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   193
// this applies to all methods, but requires
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   194
import scala.language.postfixOps
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   195
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   196
List(5, 2, 3, 4).sorted
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   197
List(5, 2, 3, 4) sorted
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   198
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   199
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   200
// ...to allow the notation n + m * i
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   201
import scala.language.implicitConversions   
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   202
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   203
val i = Complex(0, 1)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   204
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   205
given Conversion[Double, Complex] = (re => Complex(re, 0))
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   206
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   207
val inum1 = -2.0 + -1.5 * i
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   208
val inum2 =  1.0 +  1.5 * i
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   209
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   210
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   211
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   212
// All is public by default....so no public is needed.
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   213
// You can have the usual restrictions about private 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   214
// values and methods, if you are MUTABLE !!!
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   215
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   216
case class BankAccount(init: Int) {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   217
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   218
  private var balance = init
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   219
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   220
  def deposit(amount: Int): Unit = {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   221
    if (amount > 0) balance = balance + amount
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   222
  }
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   223
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   224
  def withdraw(amount: Int): Int =
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   225
    if (0 < amount && amount <= balance) {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   226
      balance = balance - amount
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   227
      balance
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   228
    } else throw new Error("insufficient funds")
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   229
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   230
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   231
// BUT since we are completely IMMUTABLE, this is 
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   232
// virtually of no concern to us.
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   233
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   234
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   235
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   236
// another example about Fractions
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   237
import scala.language.implicitConversions
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   238
import scala.language.reflectiveCalls
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   239
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   240
case class Fraction(numer: Int, denom: Int) {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   241
  override def toString = numer.toString + "/" + denom.toString
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   242
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   243
  def +(other: Fraction) = 
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   244
    Fraction(numer * other.denom + other.numer * denom, 
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   245
             denom * other.denom)
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   246
  def *(other: Fraction) = 
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   247
    Fraction(numer * other.numer, denom * other.denom)
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   248
 }
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   249
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   250
given Conversion[Int, Fraction] = (x => Fraction(x, 1))
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   251
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   252
val half = Fraction(1, 2)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   253
val third = Fraction (1, 3)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   254
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   255
half + third
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   256
half * third
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   257
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   258
1 + half
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   259
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   260
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   261
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   262
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   263
// DFAs in Scala  
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   264
//===============
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   265
import scala.util.Try
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   266
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   267
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   268
// A is the state type
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   269
// C is the input (usually characters)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   270
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   271
case class DFA[A, C](start: A,              // starting state
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   272
                     delta: (A, C) => A,    // transition function
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   273
                     fins:  A => Boolean) { // final states (Set)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   274
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   275
  def deltas(q: A, s: List[C]) : A = s match {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   276
    case Nil => q
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   277
    case c::cs => deltas(delta(q, c), cs)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   278
  }
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   279
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   280
  def accepts(s: List[C]) : Boolean = 
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   281
    Try(fins(deltas(start, s))).getOrElse(false)
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   282
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   283
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   284
// the example shown in the handout 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   285
abstract class State
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   286
case object Q0 extends State
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   287
case object Q1 extends State
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   288
case object Q2 extends State
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   289
case object Q3 extends State
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   290
case object Q4 extends State
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   291
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   292
val delta : (State, Char) => State = 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   293
  { case (Q0, 'a') => Q1
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   294
    case (Q0, 'b') => Q2
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   295
    case (Q1, 'a') => Q4
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   296
    case (Q1, 'b') => Q2
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   297
    case (Q2, 'a') => Q3
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   298
    case (Q2, 'b') => Q2
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   299
    case (Q3, 'a') => Q4
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   300
    case (Q3, 'b') => Q0
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   301
    case (Q4, 'a') => Q4
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   302
    case (Q4, 'b') => Q4 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   303
    case _ => throw new Exception("Undefined") }
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   304
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   305
val dfa = DFA(Q0, delta, Set[State](Q4))
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   306
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   307
dfa.accepts("abaaa".toList)     // true
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   308
dfa.accepts("bbabaab".toList)   // true
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   309
dfa.accepts("baba".toList)      // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   310
dfa.accepts("abc".toList)       // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   311
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   312
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   313
// NFAs (Nondeterministic Finite Automata)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   314
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   315
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   316
case class NFA[A, C](starts: Set[A],          // starting states
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   317
                     delta: (A, C) => Set[A], // transition function
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   318
                     fins:  A => Boolean) {   // final states 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   319
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   320
  // given a state and a character, what is the set of 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   321
  // next states? if there is none => empty set
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   322
  def next(q: A, c: C) : Set[A] = 
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   323
    Try(delta(q, c)).getOrElse(Set[A]()) 
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   324
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   325
  def nexts(qs: Set[A], c: C) : Set[A] =
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   326
    qs.flatMap(next(_, c))
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   327
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   328
  // depth-first version of accepts
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   329
  def search(q: A, s: List[C]) : Boolean = s match {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   330
    case Nil => fins(q)
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   331
    case c::cs => next(q, c).exists(search(_, cs))
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   332
  }
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   333
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   334
  def accepts(s: List[C]) : Boolean =
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   335
    starts.exists(search(_, s))
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   336
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   337
046f37a262d0 updated
updated
parents: 226
diff changeset
   338
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   339
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   340
// NFA examples
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   341
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   342
val nfa_trans1 : (State, Char) => Set[State] = 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   343
  { case (Q0, 'a') => Set(Q0, Q1) 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   344
    case (Q0, 'b') => Set(Q2) 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   345
    case (Q1, 'a') => Set(Q1) 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   346
    case (Q2, 'b') => Set(Q2) }
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   347
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   348
val nfa = NFA(Set[State](Q0), nfa_trans1, Set[State](Q2))
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   349
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   350
nfa.accepts("aa".toList)             // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   351
nfa.accepts("aaaaa".toList)          // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   352
nfa.accepts("aaaaab".toList)         // true
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   353
nfa.accepts("aaaaabbb".toList)       // true
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   354
nfa.accepts("aaaaabbbaaa".toList)    // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   355
nfa.accepts("ac".toList)             // false
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   356
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   357
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   358
// Q: Why the kerfuffle about the polymorphic types in DFAs/NFAs?
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   359
// A: Subset construction. Here the state type for the DFA is
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   360
//    sets of states.
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   361
383
c02929f2647c updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 380
diff changeset
   362
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   363
def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   364
  DFA(nfa.starts, 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   365
      { case (qs, c) => nfa.nexts(qs, c) }, 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   366
      _.exists(nfa.fins))
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   367
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   368
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   369
subset(nfa).accepts("aa".toList)             // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   370
subset(nfa).accepts("aaaaa".toList)          // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   371
subset(nfa).accepts("aaaaab".toList)         // true
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   372
subset(nfa).accepts("aaaaabbb".toList)       // true
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   373
subset(nfa).accepts("aaaaabbbaaa".toList)    // false
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   374
subset(nfa).accepts("ac".toList)             // false
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   375
384
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   376
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   377
// Laziness with style
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   378
//=====================
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   379
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   380
// The concept of lazy evaluation doesn’t really 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   381
// exist in non-functional languages. C-like languages
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   382
// are (sort of) strict. To see the difference, consider
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   383
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   384
def square(x: Int) = x * x
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   385
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   386
square(42 + 8)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   387
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   388
// This is called "strict evaluation".
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   389
470
86a456f8cb92 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 455
diff changeset
   390
// In contrast say we have a pretty expensive operation:
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   391
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   392
def peop(n: BigInt): Boolean = peop(n + 1) 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   393
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   394
val a = "foo"
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   395
val b = "foo"
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   396
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   397
if (a == b || peop(0)) println("true") else println("false")
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   398
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   399
// This is called "lazy evaluation":
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   400
// you delay compuation until it is really 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   401
// needed. Once calculated though, the result
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   402
// does not need to be re-calculated.
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   403
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   404
// A useful example is
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   405
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   406
def time_needed[T](i: Int, code: => T) = {
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   407
  val start = System.nanoTime()
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   408
  for (j <- 1 to i) code
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   409
  val end = System.nanoTime()
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   410
  f"${(end - start) / (i * 1.0e9)}%.6f secs"
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   411
}
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   412
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   413
// A slightly less obvious example: Prime Numbers.
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   414
// (I do not care how many) primes: 2, 3, 5, 7, 9, 11, 13 ....
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   415
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   416
def generatePrimes (s: LazyList[Int]): LazyList[Int] =
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   417
  s.head #:: generatePrimes(s.tail.filter(_ % s.head != 0))
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   418
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   419
val primes = generatePrimes(LazyList.from(2))
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   420
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   421
// the first 10 primes
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   422
primes.take(100).toList
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   423
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   424
time_needed(1, primes.filter(_ > 100).take(3000).toList)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   425
time_needed(1, primes.filter(_ > 100).take(3000).toList)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   426
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   427
// A Stream (LazyList) of successive numbers:
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   428
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   429
LazyList.from(2).take(10)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   430
LazyList.from(2).take(10).force
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   431
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   432
// An Iterative version of the Fibonacci numbers
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   433
def fibIter(a: BigInt, b: BigInt): LazyList[BigInt] =
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   434
  a #:: fibIter(b, a + b)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   435
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   436
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   437
fibIter(1, 1).take(10).force
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   438
fibIter(8, 13).take(10).force
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   439
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   440
fibIter(1, 1).drop(10000).take(1)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   441
fibIter(1, 1).drop(10000).take(1).force
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   442
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   443
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   444
// LazyLists are good for testing
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   445
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   446
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   447
// Regular expressions - the power of DSLs in Scala
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   448
//                                     and Laziness
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   449
//==================================================
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   450
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   451
abstract class Rexp
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   452
case object ZERO extends Rexp                     // nothing
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   453
case object ONE extends Rexp                      // the empty string
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   454
case class CHAR(c: Char) extends Rexp             // a character c
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   455
case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   456
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2  
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   457
case class STAR(r: Rexp) extends Rexp             // star         r*
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   458
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   459
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   460
// some convenience for typing in regular expressions
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   461
import scala.language.implicitConversions    
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   462
import scala.language.reflectiveCalls 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   463
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   464
def charlist2rexp(s: List[Char]): Rexp = s match {
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   465
  case Nil => ONE
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   466
  case c::Nil => CHAR(c)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   467
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   468
}
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   469
481
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   470
given Conversion[String, Rexp] = (s => charlist2rexp(s.toList))
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   471
e03a0100ec46 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 470
diff changeset
   472
extension (r: Rexp) {
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   473
  def | (s: Rexp) = ALT(r, s)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   474
  def % = STAR(r)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   475
  def ~ (s: Rexp) = SEQ(r, s)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   476
}
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   477
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   478
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   479
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   480
//example regular expressions
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   481
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   482
val sign = "+" | "-" | ""
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   483
val number = sign ~ digit ~ digit.% 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   484
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   485
// Task: enumerate exhaustively regular expressions
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   486
// starting from small ones towards bigger ones.
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   487
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   488
// 1st idea: enumerate them all in a Set
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   489
// up to a level
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   490
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   491
def enuml(l: Int, s: String) : Set[Rexp] = l match {
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   492
  case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   493
  case n =>  
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   494
    val rs = enuml(n - 1, s)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   495
    rs ++
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   496
    (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   497
    (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   498
    (for (r1 <- rs) yield STAR(r1))
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   499
}
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   500
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   501
enuml(1, "a")
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   502
enuml(1, "a").size
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   503
enuml(2, "a").size
470
86a456f8cb92 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 455
diff changeset
   504
enuml(3, "a").size 
86a456f8cb92 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 455
diff changeset
   505
enuml(4, "a").size // out of heap space
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   506
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   507
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   508
def enum(rs: LazyList[Rexp]) : LazyList[Rexp] = 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   509
  rs #::: enum( (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #:::
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   510
                (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #:::
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   511
                (for (r1 <- rs) yield STAR(r1)) )
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   512
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   513
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   514
enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force
470
86a456f8cb92 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 455
diff changeset
   515
enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000).force // out of memory
455
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   516
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   517
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   518
def depth(r: Rexp) : Int = r match {
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   519
  case ZERO => 0
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   520
  case ONE => 0
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   521
  case CHAR(_) => 0
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   522
  case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   523
  case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   524
  case STAR(r1) => depth(r1) + 1
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   525
}
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   526
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   527
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   528
val is = 
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   529
  (enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b')))
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   530
    .dropWhile(depth(_) < 3)
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   531
    .take(10).foreach(println))
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   532
557d18cce0f0 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 418
diff changeset
   533
384
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   534
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   535
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   536
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   537
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   538
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   539
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   540
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   541
6e1237691307 updated
Christian Urban <christian.urban@kcl.ac.uk>
parents: 383
diff changeset
   542
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   543
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   544
240
b8cdaf51ffef updated
Christian Urban <urbanc@in.tum.de>
parents: 238
diff changeset
   545
// The End ... Almost Christmas
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   546
//===============================
046f37a262d0 updated
updated
parents: 226
diff changeset
   547
046f37a262d0 updated
updated
parents: 226
diff changeset
   548
// I hope you had fun!
046f37a262d0 updated
updated
parents: 226
diff changeset
   549
046f37a262d0 updated
updated
parents: 226
diff changeset
   550
// A function should do one thing, and only one thing.
046f37a262d0 updated
updated
parents: 226
diff changeset
   551
046f37a262d0 updated
updated
parents: 226
diff changeset
   552
// Make your variables immutable, unless there's a good 
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   553
// reason not to. Usually there is not.
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   554
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   555
// I did it once, but this is actually not a good reason:
240
b8cdaf51ffef updated
Christian Urban <urbanc@in.tum.de>
parents: 238
diff changeset
   556
// generating new labels:
b8cdaf51ffef updated
Christian Urban <urbanc@in.tum.de>
parents: 238
diff changeset
   557
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   558
var counter = -1
222
e52cc402caee updated
Christian Urban <urbanc@in.tum.de>
parents: 218
diff changeset
   559
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   560
def Fresh(x: String) = {
046f37a262d0 updated
updated
parents: 226
diff changeset
   561
  counter += 1
046f37a262d0 updated
updated
parents: 226
diff changeset
   562
  x ++ "_" ++ counter.toString()
046f37a262d0 updated
updated
parents: 226
diff changeset
   563
}
046f37a262d0 updated
updated
parents: 226
diff changeset
   564
046f37a262d0 updated
updated
parents: 226
diff changeset
   565
Fresh("x")
046f37a262d0 updated
updated
parents: 226
diff changeset
   566
Fresh("x")
046f37a262d0 updated
updated
parents: 226
diff changeset
   567
046f37a262d0 updated
updated
parents: 226
diff changeset
   568
046f37a262d0 updated
updated
parents: 226
diff changeset
   569
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   570
// I think you can be productive on Day 1, but the 
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   571
// language is deep.
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   572
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   573
// http://scalapuzzlers.com
046f37a262d0 updated
updated
parents: 226
diff changeset
   574
//
046f37a262d0 updated
updated
parents: 226
diff changeset
   575
// http://www.latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/
046f37a262d0 updated
updated
parents: 226
diff changeset
   576
328
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   577
val two   = 0.2
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   578
val one   = 0.1
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   579
val eight = 0.8
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   580
val six   = 0.6
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   581
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   582
two - one == one
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   583
eight - six == two
329
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   584
eight - six
328
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   585
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   586
329
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   587
// problems about equality and type-errors
328
0e591f806290 updated
Christian Urban <urbanc@in.tum.de>
parents: 326
diff changeset
   588
329
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   589
List(1, 2, 3).contains("your cup")   // should not compile, but retruns false
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   590
8a34b2ebc8cc updated
Christian Urban <urbanc@in.tum.de>
parents: 328
diff changeset
   591
List(1, 2, 3) == Vector(1, 2, 3)     // again should not compile, but returns true
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   592
238
046f37a262d0 updated
updated
parents: 226
diff changeset
   593
326
e5453add7df6 updated
Christian Urban <urbanc@in.tum.de>
parents: 247
diff changeset
   594