Instructor: James Riely
Option
type
List
type
Int
and String
case class C (x:Int, y:String)
new
unnecessary for constructing instances
val c:C = C (5, "hello")
val n:Int = c match
case C (a, b) => a
case
classes
case class C (x:Int, y:String)
val c:C = C (5, "hello")
val a:Int = c.x
c.x = 6 // error: reassignment to val
toString
implementation
apply
method
unapply
method / extractors in textbook
Tuple3.scala
source
case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3)
extends Product3[T1, T2, T3]:
override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")"
scala> (5, "hello", true).getClass
res0: Class[_ <: (Int, String, Boolean)] = class scala.Tuple3
trait
similar to Java interface
sealed trait DateSpecifier
case class Absolute (year:Int,mon:Int,day:Int) extends DateSpecifier
case class Relative (daysOffset:Int) extends DateSpecifier
enum
s are awesome!
enum DateSpecifier:
case Absolute (year:Int,mon:Int,day:Int)
case Relative (daysOffset:Int)
val ds = new Array[DateSpecifier] (2)
ds (0) = DateSpecifier.Absolute (2022, 11, 1)
ds (1) = DateSpecifier.Relative (-5)
import DateSpecifier.*
def resolveDate (d:DateSpecifier) : String =
d match
case Absolute (y, m, d) => "%04d-%02d-%02d".format(y, m, d)
case Relative (o) => java.time.LocalDate.now.plusDays(o).toString
ds map resolveDate
struct s_absolute_t {
int year;
int mon;
int day;
};
struct s_relative_t {
int days_offset;
};
union u_ds_t {
struct s_absolute_t u_absolute;
struct s_relative_t u_relative;
};
enum e_ds_t {
e_absolute,
e_relative,
};
struct ds_t {
enum e_ds_t tag;
union u_ds_t content;
};
struct ds_t ds[2];
ds[0].tag = e_absolute;
ds[0].content.u_absolute.year = 2030;
ds[0].content.u_absolute.mon = 0;
ds[0].content.u_absolute.day = 1;
ds[1].tag = e_relative;
ds[1].content.u_relative.days_offset = -5;
void print_ds (struct ds_t *dsp) {
switch (dsp->tag) {
case e_absolute:
printf ("absolute (%d, %d, %d)\n", dsp->content.u_absolute.year,
dsp->content.u_absolute.mon,
dsp->content.u_absolute.day);
break;
case e_relative:
printf ("relative (%d)\n", dsp->content.u_relative.days_offset);
break;
default:
fprintf (stderr, "Unknown tag\n");
exit (1);
}
}
PeanoNat
and Int
enum Peano:
case Zero
case Succ (n:Peano)
def peano2int (p:Peano): Int = p match
case Peano.Zero => 0
case Peano.Succ(n) => 1 + peano2int (n)
import Peano.*
val q = Succ (Succ (Succ (Zero))) // : Peano = ...
peano2int (q) // : Int = 3
Empty
and Cons
Empty
used at any List
type
enum MyList[+X]:
case Empty
case Cons (head:X, tail:MyList[X])
def length [X] (xs:MyList[X]): Int = xs match
case MyList.Empty => 0
case MyList.Cons(a,as) => 1 + length(as)
import MyList.*
val xs = Cons (11, Cons(21, Cons(31, Empty))) // : MyList[Int] = ...
length (xs) // : Int = 3
val ys = Empty // : MyList[Nothing] = ...
enum Tree[+K]:
case Leaf
case Node (left:Tree[K], key:K, right:Tree[K])
enum Color { case Red, Black }
enum RBTree[+K]:
case Leaf
case Node (left:RBTree[K], key:K, color:Color, right:RBTree[K])
import RBTree.*;
def rotateLeft [K] (t:Node[K]) : Node[K] =
t match
case Node (left, k1, c1, Node (mid, k2, Color.Red, right)) =>
Node (Node (left, k1, Color.Red, mid), k2, c1, right)
case _ =>
throw new RuntimeException ("does not match: " + t)