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
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.nn.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[+X]:
case Leaf
case Node (l:Tree[X], c:X, r:Tree[X])
enum Color { case Red, Black }
enum RBTree[+K,+V]:
case Leaf
case Node (k:K, v:V, c:Color, l:RBTree[K,V], r:RBTree[K,V])
import RBTree.*;
def rotateLeft [K,V] (t:Node[K,V]) : Node[K,V] =
t match
case Node (k1, v1, c, l, Node (k2, v2, Color.Red, m, r)) =>
Node (k2, v2, c, Node (k1, v1, Color.Red, l, m), r)
case _ =>
throw new RuntimeException ("does not match: " + t)