slate

Data types

data declares a closed set of variants — an algebraic data type — and that closed set is what makes a match over one worth checking.

data Shape
    Circle(r)
    Rect(w, h)
    Empty

    area(self) = self match
        Circle(r) -> 3 * r * r
        Rect(w, h) -> w * h
        Empty -> 0

print(Circle(3), Circle(3).area())
print(Empty, Empty.area())
Circle(3) 27
Empty 0

A variant is a class from the data type, which is the whole of the implementation: is Shape, an annotation, export, a cross-file import and a method on the shared body are all machinery class already had. Circle(3) is the generated constructor, reached by the rule that calling an object calls its new.

A variant that declares no fields is a value rather than a maker. Empty is the value, not Empty(), and the test for it is identity.

A data value does not change

A write to one of its fields is refused, and v with { r: 4 } answers a new one that differs there. Two equal ones are equal and hash alike, so a data value is an ordinary table key.

data Shape
    Circle(r)

val c = Circle(3)

print(c with { r: 4 }, c)
print(Circle(3) == Circle(3))
Circle(4) Circle(3)
true

Exhaustive match

A match over an annotated subject must cover every variant, and the complaint names each one left out:

data Shape
    Circle(r)
    Rect(w, h)
    Empty

sides(s: Shape) = s match
    Circle(_) -> 0
    Rect(_, _) -> 4
    Empty -> 0

print(sides(Circle(1)), sides(Rect(1, 2)), sides(Empty))
0 4 0

It is checked exactly where the shape was written down — an unannotated subject is said nothing about — and a _ arm is how a program says it has finished listing.

Patterns

Variants take the same two forms a class does — Circle(r) by position, Circle { r } by name — and a field name the variant does not carry is refused where it is written. See Patterns.

The data name and each variant name are shape values, so Figure.test(v) asks whether v was made by one of the variants and Circle.test(v) asks about that one — the run-time form of the is above. mismatch and name come with them; see Types.

Encoding

Without a toJSON, a variant encodes as its own fields: Circle(3) is {"r":3}, never the chain it hangs from. A toJSON(self) on the shared body says otherwise — see Objects.

Search

Esc
to navigate to open Esc to close