Data Types (Immutable)
In Slang data type declarations, fields are given a name and type as
part of the Scala class signature, which defines the only constructor.
Since data types are immutable, the fields are always considered to be
val
fields, even when the val
qualifier is omitted.
Data types can have additional fields beyond those in given in the class signature, and their immutable values must be specified in terms of other variables in scope at the point of instance creation.
All types of data type fields must be immutable.
Data types can also have methods, but corresponding to the immutability of the data type, these cannot modify field values.
Note
JH: To Robby, can we consider these methods to be implicitly @pure?
// Each Slang class must have a @datatype or @record annotation.
// @datatype are immutable structures
// ...they can only contain val fields and immutable objects
@datatype class Coordinate(x: Z, val y: Z) {
// Declare fields in constructor.
// Val can be omitted, but such fields are implicitly "val".
val isCenter: B = x == 0 && y == 0 // additional fields can be declared that
// derive their values from the (immutable) state
// of constructor fields.
// Explicit type declaration is required.
// The class may include methods that don't change the state of the object
def isEqualX(other: Coordinate): B = {
return x == other.x
}
def isEqualY(other: Coordinate): B = {
return y == other.y
}
}
As with Scala case classes, one does not use the keyword new
when
creating instances of Slang data types (Slang record creation also
omits new
). Slang data types and records are compared using
structural equality. Slang also provides a convenient syntax for
creating copies of previous instances (this is somewhat analogous to
implicitly using the copy
method of Scala case classes – see
here).
// example client actions
val c1 = Coordinate(3, 4) // create an instance of the data type class
assert(!c1.isCenter)
val c2 = c1(x = 5) // produces a new instance (copy) where its x is 5 and its y is c1.y
assert(!c1.isEqualX(c2) && c1.isEqualY(c2))
assert(c1 == c2(x = 3)) // create a new instance derived from c2
// assertion succeeds due to structural equality
var c3 = c1 // One can have a *variable* that refers to *immutable* objects
c3 = c2 // Even though the data structure itself is immutable (we can't change the fields),
// the variable reference is mutable (we can assign different instances to it).
The last few lines in the above example illustrate the difference
between the notions of mutability of a data structure and mutability
of a Slang variable: one can have a var
that can be updated
(mutated) to reference different immutable structures.