case classescase 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 implementationapply method
unapply method / extractors in textbookTuple3.scala sourcecase 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
enum similar to Java interfaceenum DateSpecifier:
case Absolute (year:Int,mon:Int,day:Int)
case Relative (daysOffset:Int)
val ds = new Array[DateSpecifier] (2)
ds (0) = DateSpecifier.Absolute (2030, 0, 1) // Months are 0.11
ds (1) = DateSpecifier.Relative (-5)
import java.util.{Calendar,Date}
def resolveDate (d:DateSpecifier) : Calendar =
val b = Calendar.Builder()
d match
case DateSpecifier.Absolute (y, m, d) => b.setDate (y, m, d).build
case DateSpecifier.Relative (o) =>
val c = b.build // Jan 1 1970, Gregorian calendar
c.setTime (Date()) // Today, Gregorian calendar
c.add (Calendar.DAY_OF_YEAR, o) // Add days offset
c // Return updated calendar object
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);
}
}
PeanoNatenum PeanoNat:
case Zero
case Succ (n:PeanoNat)
PeanoNat and Intdef peano2int (p:PeanoNat): Int = p match
case PeanoNat.Zero => 0
case PeanoNat.Succ(n) => 1 + peano2int (n)
import PeanoNat.*
val q = Succ (Succ (Succ (Zero))) // : Peano = ...
peano2int (q) // : Int = 3
Which case classes and case objects?
Empty list and a Cons cell of at least one elementenum MyList:
case Empty
case Cons (head:Int, tail:MyList)
enum MyList:
case Empty
case Cons (head:Int, tail:MyList)
Create an empty list?
Simply use Empty
import MyList.*
val xs = Empty
Create an instance of a list?
Nest Cons and terminate with Empty
import MyList.*
val xs = Cons (11, Cons(21, Cons(31, Empty)))
// xs : MyList[Int] = ...
Generalize to any element type?
enum MyList[+X]:
case Empty
case Cons (head:X, tail:MyList[X])
Compute the length of such a list?
def length [X] (xs:MyList[X]): Int = xs match
case MyList.Empty => 0
case MyList.Cons(a,as) => 1 + length(as)
enum Tree[X]:
case Leaf (data:X)
case Node (l:Tree[X], f:(X,X)=>X, r:Tree[X])
Fold tree into result by applying all the intermediate operations
Recursive with pattern matching
def fold [X] (t: Tree[X]) : X = t match
case Leaf(x) => x
case Node(l, f, r) => f(fold(l), fold(r))
enum and case classes