--- a/progs/lecture5.scala Mon Nov 06 21:49:55 2023 +0000
+++ b/progs/lecture5.scala Fri Dec 08 00:54:36 2023 +0000
@@ -1,7 +1,91 @@
// Scala Lecture 5
//=================
-// (Immutable)
+// extension methods
+// implicit conversions
+// (Immutable) OOP
+
+// Cool Stuff in Scala
+//=====================
+
+
+// Extensions or How to Pimp your Library
+//======================================
+//
+// For example adding your own methods to Strings:
+// Imagine you want to increment strings, like
+//
+// "HAL".increment
+//
+// you can avoid ugly fudges, like a MyString, by
+// using implicit conversions.
+
+extension (s: String) {
+ def increment = s.map(c => (c + 1).toChar)
+}
+
+"HAL".increment
+
+
+
+
+import scala.concurrent.duration.{TimeUnit,SECONDS,MINUTES}
+
+case class Duration(time: Long, unit: TimeUnit) {
+ def +(o: Duration) =
+ Duration(time + unit.convert(o.time, o.unit), unit)
+}
+
+extension (that: Int) {
+ def seconds = Duration(that, SECONDS)
+ def minutes = Duration(that, MINUTES)
+}
+
+2.minutes + 60.seconds
+5.seconds + 2.minutes //Duration(125, SECONDS )
+
+
+// Regular expressions - the power of DSLs in Scala
+// and Laziness
+//==================================================
+
+abstract class Rexp
+case object ZERO extends Rexp // nothing
+case object ONE extends Rexp // the empty string
+case class CHAR(c: Char) extends Rexp // a character c
+case class ALT(r1: Rexp, r2: Rexp) extends Rexp // alternative r1 + r2
+case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence r1 . r2
+case class STAR(r: Rexp) extends Rexp // star r*
+
+
+// some convenience for typing in regular expressions
+import scala.language.implicitConversions
+import scala.language.reflectiveCalls
+
+def charlist2rexp(s: List[Char]): Rexp = s match {
+ case Nil => ONE
+ case c::Nil => CHAR(c)
+ case c::s => SEQ(CHAR(c), charlist2rexp(s))
+}
+
+given Conversion[String, Rexp] = (s => charlist2rexp(s.toList))
+
+extension (r: Rexp) {
+ def | (s: Rexp) = ALT(r, s)
+ def % = STAR(r)
+ def ~ (s: Rexp) = SEQ(r, s)
+}
+
+
+
+//example regular expressions
+val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+val sign = "+" | "-" | ""
+val number = sign ~ digit ~ digit.%
+
+
+
+
// Object Oriented Programming in Scala
// =====================================
@@ -38,9 +122,15 @@
def denom = y
}
-val half = new Fraction(1, 2)
+val half = Fraction(1, 2)
half.numer
+// does not work with "vanilla" classes
+half match {
+ case Fraction(x, y) => x / y
+}
+
+
case class Fraction(numer: Int, denom: Int)
val half = Fraction(1, 2)
@@ -48,6 +138,11 @@
half.numer
half.denom
+// works with case classes
+half match {
+ case Fraction(x, y) => x / y
+}
+
// In mandelbrot.scala I used complex (imaginary) numbers
// and implemented the usual arithmetic operations for complex
@@ -55,7 +150,7 @@
case class Complex(re: Double, im: Double) {
// represents the complex number re + im * i
- def foo(that: Complex) = Complex(this.re + that.re, this.im + that.im)
+ def +(that: Complex) = Complex(this.re + that.re, this.im + that.im)
def -(that: Complex) = Complex(this.re - that.re, this.im - that.im)
def *(that: Complex) = Complex(this.re * that.re - this.im * that.im,
this.re * that.im + that.re * this.im)
@@ -63,9 +158,11 @@
def abs = Math.sqrt(this.re * this.re + this.im * this.im)
}
-object.method(....)
+// usual way to reference methods
+//object.method(....)
-val test = Complex(1, 2) + Complex (3, 4)
+val test = Complex(1, 2) + (Complex (3, 4))
+
import scala.language.postfixOps
(List(5,4,3,2,1) sorted) reverse
@@ -84,8 +181,8 @@
import scala.language.implicitConversions
val i = Complex(0, 1)
-implicit def double2complex(re: Double) = Complex(re, 0)
+given Conversion[Double, Complex] = (re => Complex(re, 0))
val inum1 = -2.0 + -1.5 * i
val inum2 = 1.0 + 1.5 * i
@@ -126,10 +223,11 @@
def +(other: Fraction) =
Fraction(numer * other.denom + other.numer * denom,
denom * other.denom)
- def *(other: Fraction) = Fraction(numer * other.numer, denom * other.denom)
+ def *(other: Fraction) =
+ Fraction(numer * other.numer, denom * other.denom)
}
-implicit def Int2Fraction(x: Int) = Fraction(x, 1)
+given Conversion[Int, Fraction] = (x => Fraction(x, 1))
val half = Fraction(1, 2)
val third = Fraction (1, 3)
@@ -255,8 +353,6 @@
subset(nfa).accepts("aaaaabbbaaa".toList) // false
subset(nfa).accepts("ac".toList) // false
-import scala.math.pow
-
// Laziness with style
//=====================
@@ -350,24 +446,15 @@
case c::Nil => CHAR(c)
case c::s => SEQ(CHAR(c), charlist2rexp(s))
}
-implicit def string2rexp(s: String): Rexp =
- charlist2rexp(s.toList)
-implicit def RexpOps (r: Rexp) = new {
+given Conversion[String, Rexp] = (s => charlist2rexp(s.toList))
+
+extension (r: Rexp) {
def | (s: Rexp) = ALT(r, s)
def % = STAR(r)
def ~ (s: Rexp) = SEQ(r, s)
}
-implicit def stringOps (s: String) = new {
- def | (r: Rexp) = ALT(s, r)
- def | (r: String) = ALT(s, r)
- def % = STAR(s)
- def ~ (r: Rexp) = SEQ(s, r)
- def ~ (r: String) = SEQ(s, r)
-}
-
-
//example regular expressions