Peeper

Structs and type aliases

Struct literals, moves, and other names for a type.

Structs

struct names a group of fields. Name.{ field = value } makes one, with the fields in any order. .{ ... } takes the type from where the value goes.

struct Point { x: i32, y: i32 }
let start = Point.{ y = 2, x = 1 };
let end: Point = .{ x = 4, y = 6 };

Moves

A struct moves when it is assigned or passed. The old variable is then unset. A mut variable can be set again, and then it is usable again. Using a moved variable is an error that shows where the move happened:

peeper check
[T0034]: `point` is used after it was moved  --> src/main.peep:6:13  | 4 |     let point = Point.{ x = 1, y = 2 };5 |     let taken = point;  |                 ----- `point` is moved here6 |     println(point.x, taken.x);  |             ^^^^^^^ `point` is used here  |   = note: a value moves when used by value, unless its type copies  = help: set `point` again before this use, or stop moving itCompilation failed with 1 error(s)
examples/09_structs.peep
// Structs: `struct` names a group of fields. `Name.{ field = value }` makes
// one, with the fields in any order, and `.{ ... }` takes the type from
// where it goes. A struct moves when assigned or passed: the old variable
// is then unset, until a `mut` one is set again.
// Run: peeper run examples/09_structs.peep
struct Point { x: i32, y: i32 }
struct Line { start: Point, end: Point, weight: f32 }
struct Empty {}

fn length(line: Line) -> i32 {      // takes the line, moved in
    return line.end.x - line.start.x + line.end.y - line.start.y;
}

fn main() {
    let start = Point.{ y = 2, x = 1 };
    let end: Point = .{ x = 4, y = 6 };
    let mut line = Line.{ start = start, end = end, weight = 1.5 };
    line.start.x = 0;               // a field of a field
    line.weight = 2.0;
    println("line:", line);
    println("fields:", line.start.x, line.end.y, line.weight);
    println("length:", length(line));   // `line` moves; it is unset now

    let mut point = Point.{ x = 1, y = 1 };
    let taken = point;              // moves `point`
    point = Point.{ x = taken.y, y = 5 };   // set again, so usable
    println("again:", point, taken);
    println("empty:", Empty.{});
}
Output
line: Line { start: Point { x: 0, y: 2 }, end: Point { x: 4, y: 6 }, weight: 2.0 }
fields: 0 6 2.0
length: 8
again: Point { x: 1, y: 5 } Point { x: 1, y: 1 }
empty: Empty {}

Type aliases

type Name = T gives T another name. Values of the alias and of T mix freely, and an alias can name a type declared after it.

examples/10_type_aliases.peep
// Type aliases: `type Name = T` gives `T` another name. A value of the alias
// and of `T` mix freely; an alias may name one declared after it.
// Run: peeper run examples/10_type_aliases.peep
type Distance = Meters;
type Meters = i32;
type Origin = Point;
struct Point { x: Meters, y: Meters }

const Limit: Meters = 40;

fn double(length: Meters) -> Distance {
    return length * 2;
}

fn main() {
    let half: Meters = 21;
    let whole: i32 = double(half);  // a `Distance` is an `i32`
    let home: Origin = Point.{ x = 0, y = whole };
    println("whole:", whole, "over limit:", whole > Limit, "home:", home);
}
Output
whole: 42 over limit: true home: Point { x: 0, y: 42 }

On this page