Use the struct type when creating values that contain multiple other values within. A struct's member values are called properties. Each property has a unique name, a specified type, and possibly a default value.

As with other types, a struct may implement methods in addition to properties. Additionally, structs may implement traits and/or variant-type tags, useful features described elsewhere.

Note: structs are not the only type to support properties. Traits, Interfaces, Allocs, Perms and other types also support properties for similar, but more specialized needs.

Declaration

First, you must declare a specific struct layout by name. For example:

struct Point
    x f32
    y f32

This defines a struct type named Point that contains two properties named x and y. Both properties are floating point numbers. It is common to capitalize the names of declared types.

Property declarations look just like variable declarations:

Once declared, the struct type may be used the same way as any other type. For example, this declares a Point variable:

imm pt Point;

Struct Values

A new struct value is created and initialized using a literal or a constructor.

Literals

A struct literal begins with the struct name followed by the initial values for all properties in curly braces.

	imm pt = Point {x: 3., y: 4.}    // Using property names
	imm pt2 = Point {3., 4.}         // When property names are omitted, order matters.
	

Several rules apply to literals:

Copy vs. Move

Wherever possible, structs (like numbers) are copied whenever assigned to a variable or property, passed as a parameter, or returned as a value. Any change to one copy has no effect on the others.

imm pt = Point {x: 3f, y:4f}
imm pt2 = pt     // pt2 is a full copy
pt2.x = 4f       // pt2 changes but pt does not
func(pt2)        // this function call creates a third copy

However, a declared struct type will enforce move semantics if it either:

Values with move semantics are still copied to a new destination, but the original version is no longer accessible. Move semantics enforce that multiple copies of the same object cannot be usable at the same time.

struct Node
    nbr: &uni i32
uni life = 42
imm node1 = Node {nbr: &uni life}
imm node2 = node1
imm node3 = node1   // ERROR! node1 is no longer usable

Object References

struct copying has two potential limitations: a) the larger the struct, the slower the copy, b) changing a copy does not change the original. It is possible to address these limitations by borrowing a reference to a struct and then passing around and using the reference in place of the struct.

fn main()
  imm pt = Point {x: 3f, y: 4f}
  imm dist = dist(&mut pt)  // dist may modify the contents of pt

Similarly, an allocator may be used to allocate a new struct. The allocator returns a reference to the struct:

imm pt = &gc mut Point{x: 3f, y: 4f}

Property Access

Any public property within a struct may be accessed using the . operator, specifying the object on the left and the property name on the right:

imm dist = (pt.x*pt.x + pt.y*pt.y).sqrt

Within a struct's methods, only the property name needs to be specified, just as if it were a variable.

fn dist() f32
    (x*x + y*y).sqrt  // x is equivalent to self.x

A property can be changed by putting the property name to the left of an assignment operator:

fn setOrigin(self &mut)
    x,y = 0f,0f

Note: From the outside, a property and a computed property (a get/set method) look identical. The user of a struct does not care if it is working with a stored value or a value mediated by methods.

Property permissions

Mutation of a property is allowed only if the permissions on both the object and the property permit it.

Property references

It is possible to use the & operator to obtain a borrowed reference to a specific property within a structure:

imm pt = Point{x: 3f, y: 4f}
imm refx = &pt.x
*refx                     // 3f

Structs as Closures

If a struct implements the `()` method, it can be utilized in a very similar way to what other languages call a closure. In effect, it is callable (like a first class function), but preserves a bound state from one execution to the next.

_