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