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)) ++  |