|      1 // Scala Lecture 5 |      1 // Scala Lecture 5 | 
|      2 //================= |      2 //================= | 
|      3  |      3  | 
|      4 for (n <- (1 to 10).toList) yield { |      4 def foo(n: Int) = ??? | 
|      5   val add = 10 |      5  | 
|      6   n + add |      6 fop(10) | 
|      7 } |      7  | 
|      8  |      8 List.fill(1)(100) | 
|      9 println(add) |         | 
|     10  |         | 
|     11 List(1,2,3,4).sum |         | 
|     12  |         | 
|     13 // extension methods |         | 
|     14 // implicit conversions |         | 
|     15 // (Immutable) OOP |      9 // (Immutable) OOP | 
|     16  |         | 
|     17 // Cool Stuff in Scala |         | 
|     18 //===================== |         | 
|     19  |         | 
|     20  |         | 
|     21 // Extensions or How to Pimp your Library |         | 
|     22 //====================================== |         | 
|     23  |         | 
|     24 // For example adding your own methods to Strings: |         | 
|     25 // Imagine you want to increment strings, like |         | 
|     26 // |         | 
|     27 //     "HAL".increment |         | 
|     28 // |         | 
|     29 // you can avoid ugly fudges, like a MyString, by |         | 
|     30 // using extensions. |         | 
|     31  |         | 
|     32 extension (s: String) { |         | 
|     33   def increment = s.map(c => (c + 1).toChar) |         | 
|     34 } |         | 
|     35  |         | 
|     36 "HAL".increment |         | 
|     37  |         | 
|     38  |         | 
|     39  |         | 
|     40 // a more relevant example |         | 
|     41  |         | 
|     42 import scala.concurrent.duration.{TimeUnit,SECONDS,MINUTES} |         | 
|     43  |         | 
|     44 case class Duration(time: Long, unit: TimeUnit) { |         | 
|     45   def +(o: Duration) =  |         | 
|     46     Duration(time + unit.convert(o.time, o.unit), unit) |         | 
|     47 } |         | 
|     48  |         | 
|     49 extension (that: Int) { |         | 
|     50   def seconds = Duration(that, SECONDS) |         | 
|     51   def minutes = Duration(that, MINUTES) |         | 
|     52 } |         | 
|     53  |         | 
|     54 2.minutes + 60.seconds |         | 
|     55 5.seconds + 2.minutes   //Duration(125, SECONDS ) |         | 
|     56  |         | 
|     57  |         | 
|     58 // Implicit Conversions |         | 
|     59 //===================== |         | 
|     60  |         | 
|     61  |         | 
|     62  |         | 
|     63 // Regular expressions - the power of DSLs in Scala |         | 
|     64 //================================================== |         | 
|     65  |         | 
|     66 abstract class Rexp |         | 
|     67 case object ZERO extends Rexp                     // nothing |         | 
|     68 case object ONE extends Rexp                      // the empty string |         | 
|     69 case class CHAR(c: Char) extends Rexp             // a character c |         | 
|     70 case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative  r1 + r2 |         | 
|     71 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence     r1 . r2   |         | 
|     72 case class STAR(r: Rexp) extends Rexp             // star         r* |         | 
|     73  |         | 
|     74 val r = STAR(CHAR('a')) |         | 
|     75  |         | 
|     76  |         | 
|     77 // some convenience for typing in regular expressions |         | 
|     78 import scala.language.implicitConversions     |         | 
|     79 import scala.language.reflectiveCalls  |         | 
|     80  |         | 
|     81 def charlist2rexp(s: List[Char]): Rexp = s match { |         | 
|     82   case Nil => ONE |         | 
|     83   case c::Nil => CHAR(c) |         | 
|     84   case c::s => SEQ(CHAR(c), charlist2rexp(s)) |         | 
|     85 } |         | 
|     86  |         | 
|     87 given Conversion[String, Rexp] = (s => charlist2rexp(s.toList)) |         | 
|     88  |         | 
|     89 extension (r: Rexp) { |         | 
|     90   def | (s: Rexp) = ALT(r, s) |         | 
|     91   def % = STAR(r) |         | 
|     92   def ~ (s: Rexp) = SEQ(r, s) |         | 
|     93 } |         | 
|     94  |         | 
|     95 val r1 = CHAR('a') | CHAR('b') | CHAR('c') |         | 
|     96 val r2 = CHAR('a') ~  CHAR('b') |         | 
|     97  |         | 
|     98 val r3 : Rexp = "hello world" |         | 
|     99        |         | 
|    100  |         | 
|    101 //example regular expressions |         | 
|    102 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |         | 
|    103 val sign = "+" | "-" | "" |         | 
|    104 val number = sign ~ digit ~ digit.%  |         | 
|    105  |         | 
|    106  |         | 
|    107  |         | 
|    108  |     10  | 
|    109 // Object Oriented Programming in Scala |     11 // Object Oriented Programming in Scala | 
|    110 // ===================================== |     12 // ===================================== | 
|    111  |     13  | 
|    112  |     14  | 
|    160  |     62  | 
|    161 // works with case classes |     63 // works with case classes | 
|    162 half match { |     64 half match { | 
|    163   case Fraction(x, y) => x / y |     65   case Fraction(x, y) => x / y | 
|    164 } |     66 } | 
|    165  |         | 
|    166  |         | 
|    167 // In mandelbrot.scala I used complex (imaginary) numbers  |         | 
|    168 // and implemented the usual arithmetic operations for complex  |         | 
|    169 // numbers. |         | 
|    170  |         | 
|    171 case class Complex(re: Double, im: Double) {  |         | 
|    172   // represents the complex number re + im * i |         | 
|    173   def +(that: Complex) = Complex(this.re + that.re, this.im + that.im) |         | 
|    174   def -(that: Complex) = Complex(this.re - that.re, this.im - that.im) |         | 
|    175   def *(that: Complex) = Complex(this.re * that.re - this.im * that.im, |         | 
|    176                                  this.re * that.im + that.re * this.im) |         | 
|    177   def *(that: Double) = Complex(this.re * that, this.im * that) |         | 
|    178   def abs = Math.sqrt(this.re * this.re + this.im * this.im) |         | 
|    179 } |         | 
|    180  |         | 
|    181 // usual way to reference methods |         | 
|    182 //object.method(....) |         | 
|    183  |         | 
|    184 val test = Complex(1, 2) + (Complex (3, 4)) |         | 
|    185  |         | 
|    186  |         | 
|    187 import scala.language.postfixOps |         | 
|    188 (List(5,4,3,2,1) sorted) reverse |         | 
|    189  |         | 
|    190 // this could have equally been written as |         | 
|    191 val test = Complex(1, 2).+(Complex (3, 4)) |         | 
|    192  |         | 
|    193 // this applies to all methods, but requires |         | 
|    194 import scala.language.postfixOps |         | 
|    195  |         | 
|    196 List(5, 2, 3, 4).sorted |         | 
|    197 List(5, 2, 3, 4) sorted |         | 
|    198  |         | 
|    199  |         | 
|    200 // ...to allow the notation n + m * i |         | 
|    201 import scala.language.implicitConversions    |         | 
|    202  |         | 
|    203 val i = Complex(0, 1) |         | 
|    204  |         | 
|    205 given Conversion[Double, Complex] = (re => Complex(re, 0)) |         | 
|    206  |         | 
|    207 val inum1 = -2.0 + -1.5 * i |         | 
|    208 val inum2 =  1.0 +  1.5 * i |         | 
|    209  |     67  | 
|    210  |     68  | 
|    211  |     69  | 
|    212 // All is public by default....so no public is needed. |     70 // All is public by default....so no public is needed. | 
|    213 // You can have the usual restrictions about private  |     71 // You can have the usual restrictions about private  | 
|    487  |    345  | 
|    488 // 1st idea: enumerate them all in a Set |    346 // 1st idea: enumerate them all in a Set | 
|    489 // up to a level |    347 // up to a level | 
|    490  |    348  | 
|    491 def enuml(l: Int, s: String) : Set[Rexp] = l match { |    349 def enuml(l: Int, s: String) : Set[Rexp] = l match { | 
|    492   case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet |    350   case 0 => Set(ZERO, ONE) ++ s.map(CHAR(_)).toSet | 
|    493   case n =>   |    351   case n =>   | 
|    494     val rs = enuml(n - 1, s) |    352     val rs = enuml(n - 1, s) | 
|    495     rs ++ |    353     rs ++ | 
|    496     (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++ |    354     (for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) ++ | 
|    497     (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++ |    355     (for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) ++ |