15

I am now learning zig language. I have seen definitions of structs with const keyword like

const X = struct {
    n: i32,
};

My understanding is that const is a kind of complementary to var, the latter allows change, the former does not. But what would mean defining struct with var?

var Y = struct {
    n: i32,
};

Is this legal? I compiles, so yes, it is. But what is the meaning and use of this?

1 Answers1

20

That compiles because zig is lazy evaluated. Because Y is not used, the compiler doesn't check it.

When you reference it, the compiler throw an error:

Try this code

var Y = struct {
    n: i32,
};

comptime {
    @compileLog(Y);
}
error: variable of type 'type' must be constant
    var Y = struct {
    ^

var is to declare variables. When you use var in a global scope, that creates a global variable.

In your case,

var Y = struct {
    n: i32,
};

Declares Y as a variable of infered type. In this case, Y is a variable of type type.

In zig, there is comptime-only types, that is the case of type. A value where the type is comptime-only type only can live inside the compiler, you can't create the value in runtime1. So, the compiler needs always to comptime-known the value.

So, because Y is a global variable. You can modify it in runtime. That is the reason for the error. The value of Y cannot be generated/stored by the binary.


If only lives in the compiler, works

Try this code

comptime {
    var Y = struct {
        n: i32,
    };

    Y = struct {
        count: u32,
    };

    const concrete = Y { .count = 10 };

    @compileLog(concrete.count);
}
| 10 

Appendix

1 For example, consider

Try this code

const std = @import("std");

fn compilerKnown(arg: []const u8) type {
   return u64;
}

pub fn main() !void {
    var runtimeValue = "hello world";

    std.debug.print("{}\n", .{ compilerKnown(runtimeValue) });
}
error: unable to evaluate constant expression
    std.debug.print("{}\n", .{ compilerKnown(runtimeValue) });
                                             ^

This is an error because zig try to compile the function compilerKnown into the binary, but the type type is comptime-only, so is unable to generate the binary. In particular, cannot generate the machine code for return u64.

  • Wow, that is a perfect explanation. It seems I will have to unlearn C/C++ a bit before learning zig. :) – HiFile.app - best file manager Jun 25 '20 at 07:01
  • 3
    I have yet another question, maybe I am still missing some understanding... what is the reason that `struct`s are defined with `const` while functions are defined with very different syntax like `pub fn x(bool) void`? In my view these are both types and their definitions should share the same syntax. Why is not function defined e.g. `const x = fn(bool) -> void` (like structs) or structs defined `pub struct x { ... }` (like functions). Is there any reason behind this syntax design decision, i.e. does it allow some language features? Or was this more or less just an arbitrary decision? – HiFile.app - best file manager Jul 10 '20 at 07:57
  • 5
    Yes, there is a proposal for that: https://github.com/ziglang/zig/issues/1717 Is something that is wanted. The problem is that functions pointers has similar syntax, is more difficult to declare the function exportable, inline, etc. So, for the moment, this make the language more complex and is in contrapose to the philosophy of zig [(Zen)](https://ziglang.org/documentation/master/#Zen). – Cristobal Montecino Jul 10 '20 at 20:53
  • 1
    Thank you for the explanation. I really like the language, it has lots of amazing features. But the syntax still needs a little polishing. It seems that in version 0.7.0 the syntax will settle down. – HiFile.app - best file manager Jul 11 '20 at 06:38