51 Expression literals and constructors

Literal and constructor syntax creates ordinary Predica values. The parser keeps delimiter forms such as (...), {...}, and <...> syntactic; name resolution and expression typing then decide whether a form is a function call, a nominal constructor, a structural literal, a finite set literal, or a generic application.

Scalar Literals

Boolean, integer, real, and string literals denote scalar values. An expected type may refine the exact built-in type used for a literal, provided the literal can inhabit that type:


Boolean b = true;
Int32 n = 1;
Float32 x = 1.5;
String s = "London";

Integer literals are exact. A literal assigned to a bounded integer type must be in range. Real literals are checked against the requested floating-point or real type. Enum values are named values such as Color.red; they are not string literals.

Empty Set

Set<T> is the type of finite sets of values whose element type is T. The empty-set expression ∅ has no elements and is valid at any compatible set element type:


Set<Integer> numbers = ∅;
names ∩ ∅;
"London" ∈ ∅;

The expression ∅ does not have one fixed element type by itself. Its element type is supplied by an expected type or by surrounding set operators. A standalone empty-set expression without enough context is ambiguous.

Finite Set Literals

A primary curly expression with ordinary expression items is a finite set literal:


{1, 2, 3}
{1, 2.5}
{Color.red, Color.green}

The element type is inferred from the items, using the least common element type accepted by the type system. For example, {1, 2.5} has type Set<Real> if integer values are assignable to Real. If no common element type exists, the literal is rejected. Duplicate values do not change the denoted set.

An empty curly expression {} is an empty finite set literal only when an expected Set<T> type or equivalent context supplies the element type. Prefer ∅ when the source is specifically naming the empty set.

Integer Ranges

The range expression a..b denotes the finite set of consecutive integers from a to b, inclusive:


1..4        // {1, 2, 3, 4}
3 ∈ 1..4    // true

Both bounds must be statically evaluable integer values. The lower bound must not exceed the upper bound. An implementation may reject a range that is too large to materialise as a finite set. Range expressions are not associative; write parentheses when a range is part of a larger set expression.

Structural Literals

A curly expression with named field initializers may construct a structural value when the expected type is structural:


{ Real x; Real y; } point = { x = 1, y = 3 };

Each required structural field must be initialised exactly once, and each initializer expression is checked against the corresponding field type. Field order in the structural type remains part of the structural type identity, but the named-field literal is matched by field name.

Nominal Constructors

A nominal value or entity type introduces constructor syntax using the type name. The preferred form names the initialised attributes:


value Point
{
    Real x;
    Real y;
}

Point { x = 1, y = 3 }
Box<Integer> { value = 1 }

The constructor target must resolve to a concrete nominal type. A complete constructor initializes every required base attribute. Optional attributes may be omitted. Every supplied initializer must be assignable to the corresponding attribute type, and a constructor must not initialize an unknown, duplicate, or dropped attribute.

Constructor syntax is a convenience for initialising a value. The value above may instead be constructed programmatically:


var Point point;
point.x := 1;
point.y := 3;

The two forms are alternative ways to initialise the same kind of value. The rules for partially initialising a value through its constituent locations are specified in Uninitialised Locations.

The positional shorthand supplies constructor arguments in declaration order:


Point(1, 3)
Box<Integer>(1)

This is shorthand for the named-field constructor and is rendered canonically as the named-field form. A call-shaped expression that can resolve both as a function call and as a nominal constructor shorthand is ambiguous and must be rejected.