Structs

Ki's composite data type is a struct. A struct comprises multiple fields which can be any other type, scalars, sequences, etc. For example:

struct Position {
    var x: int
    var y: int
    var z: int
}

Using structs is straightforward:

fn main() {
    var position1: Position(1, 1, 1)

    echo("Position 1: ({{position1.x}}, {{position1.y}}, {{position1.z}})")
}

Struct fields are essentially variable declarations. Importantly however, they differ in that a value is optional. If no value is specified, then a value must be passed during initialization.

struct Actor {
    var speed:       u8(10)  # This defaults to 10
    var strength:    u8(10)  # This defaults to 10
    var name:        string  # This must be specified during initialization
    var total_health u8(100) # This defaults to 10
    var health:      u8(100) # This defaults to 100
}

fn main() {
    var actor: Actor(name: "Cyberdemon")
    var actor_health: f32(actor.health - 1)
    var actor_total_health: f32(actor.total_health)

    actor_health--

    echo("Actor health is at {{actor_health / actor_total_health}}%")
}

In this example, we have to jump through a lot of hoops just to get health as a percentage. It would be nice if Actor provided a method for this. Unfortunately though, we can't do this with just a struct: a struct is simply a bag of data and has no methods. For that, we need a type; see types for more information.

Initialization

struct Person {
    var first_name:     string
    var last_name:      string
    var favorite_color: string
    var age:            uint(0)
}

fn main() {
    var charlie1: *Person("Charlie", "Gunyon", "green", 32)

    var charlie2: *Person("Charlie", "Gunyon", "green")

    var charlie3: *Person(
        favorite_color: "green",
        last_name: "Gunyon",
        first_name: "Charlie",
        age: 32
    )

    var charlie4: *Person(first_name: "Charlie", last_name: "Gunyon",
                          favorite_color: "green", age: 32)
}

Some things worth pointing out:

  • Variables in Ki must be initialized (as previously noted), and this extends to type fields as well.
  • "Person" provides default values, which is how the initialization of "charlie2" can omit "age". We strongly recommend providing default values for all fields, or as many fields as possible. This makes it very easy to work with higher level data structures (like arrays).
  • If you don't use named parameters, you must specify parameters in order.