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