0

In case I need to declare a struct in Zig I have to prefix it with a const

const Arith = struct {
    x: i32,
    y: i32,

    fn add(self: *Arith) i32 {
        return self.x + self.y;
    }
};

test "struct test" {
    var testArith = Arith{
        .x = 9,
        .y = 9,
    };

    expect(testArith.add() == 18);
}

But it can be initialized both ways as var and const so why does the type declaration need a constant keyword when it only matters whether the instance of the struct is const or not?

Palash Nigam
  • 1,653
  • 3
  • 14
  • 26

2 Answers2

4

Need to be const because the order of evaluation in the root scope is undefined and because the variables of type type only can live in the compiler (has no memory representation, the compiler is unable to produce a binary representation of it). But you can use var inside other scopes:

comptime {
   var T = struct { value: u64 };
   
   const x: T = .{ .value = 3 };

   T = struct { ok: bool };

   const y: T = .{ .ok = true };

   @compileLog(x.value); // <- 3
   @compileLog(y.ok); // <- true
}

Run this code

In the rest of the answer, I explain in detail.

Const

const Arith = struct {...};

Creates a constant variable of a inferred type. In this case, the variable Arith has type type:

const Arith = struct {...};
comptime {
   @compileLog(@TypeOf(Arith)); // <- type
}

Run this code


This is the same as declare the variable as:

const Arith: type = struct {...};

Var

You also can create a variable with var

Examples:

comptime {
   var Arith = struct {...};
}
comptime {
   var Arith: type = struct {...};
}
fn main() !void {
   comptime var Arith = struct {...};
}
fn main() !void {
   var Arith: type = struct {...};
}
fn main() !void {
   comptime var Arith: type = struct {...};
}

Because is a variable you can modify it:

comptime {
   var T = u64;
   T = bool;
   @compileLog(T); // <-- bool
}

Run this code


Comptime Types

There is types that can only live in the compiler, like: type or structs that have a field of type anytype or other comptime type.

In the case of type, this make the compiler interpret var x: type as comptime var x: type.

Then, consider the following code:

var T = struct { value: u64 }; // <- Compiler error

comptime {
   const x: T = .{ .value = 3 };
}
error: variable of type 'type' must be constant

because the order of evaluation in the root scope is undefined, the compiler forces to create a global variable inside the binary, but the type type has no memory representation. So, the compiler raises an error.

0

Since Arith is of the type type it has to be declared a constant because the compiler expects it to be. This can be checked by changing the type declaration to this and running the program

var Arith = struct {
    x: i32,
    y: i32,

    fn add(self: *Arith) i32 {
        return self.x + self.y;
    }
};

which will result in the error error: variable of type 'type' must be constant

Also in Zig we need either a const or a var preceeding a name otherwise it is considered an invalid token.

Palash Nigam
  • 1,653
  • 3
  • 14
  • 26