# Types in zig

**URL:** <https://ziggit.dev/t/types-in-zig/5382>\
**Category:** Explain\
**Tags:** language\
**Created:** [July 27, 2024, 8:28am UTC](https://ziggit.dev/t/types-in-zig/5382 "2024-07-27T08:28:47Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ge47sil](https://ziggit.dev/letter_avatar_proxy/v4/letter/g/74df32/32.png) [@ge47sil](https://ziggit.dev/u/ge47sil)\
**Post date:** [July 27, 2024, 8:28am UTC](https://ziggit.dev/t/types-in-zig/5382/1 "2024-07-27T08:28:47Z")

</div>

I am currently experimenting with types in Zig and I came across something that I couldnt make sence of.

The Zig way of doing generics is something like this:

```zig
pub const Bra(T: type) type {
   return sturct { ... };
}

```

And I worked a bit with this ziguanic way of doing it and I like it very much. But after a while I was curious for a deeper understanding and I also had the problem what to do when I want a type to be dependent on 2 input variables and I played around and came up with this:

```zig
fn F(T: type, comptime i: usize) type {
    return struct {
        const Self = @This();
        const a: usize = i;
        const b: usize = 1337;

        fn init() Self {
            return Self{};
        }

        fn g(self: Self) usize {
            _ = self;
            return a;
        }

        fn bra(self: Self, o: Self, t: T) void {
            std.debug.print("self: {} other: {} , {}\n", .{ self.g(), o.g(), t });
        }
    };
}

```

At the beginning I thought that maybe the type of this would depend on the const elements inside the struct (because you always see this `const Self = @This();`), but after some print type information I was proven wrong.

```zig
pub fn main() void {
    const f1 = f(u32, 1);
    const f2 = f(u32, 2);

    const l1 = f1.init();
    const l2 = f2.init();
    l1.a(l2, 10)
}

```

After I tried this I got this compiler error:

```zig
src/main.zig:31:12: error: expected type 'main.F(u32,1)', found 'main.F(u32,2)'
    l1.bra(l2, 10);
           ^~
src/main.zig:5:12: note: struct declared here (2 times)
    return struct {
           ^ ~~~~~
src/main.zig:19:31: note: parameter type declared here
        fn bra(self: Self, o: Self, t: T) void 

```

So currently my assumption is that a type depends on the function call? Is there another way to declare a type? Did I miss something?

Thanks for your help!

Side questions: Is a `struct {}` of type `type`?

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [July 27, 2024, 8:52am UTC](https://ziggit.dev/t/types-in-zig/5382/2 "2024-07-27T08:52:20Z")

</div>

If I remember correctly, Types that are created at comptime are unique, even if they only vary very slightly like yours, so from your example, you are creating 2 unique type, and then you are trying to pass to the parameter self, another type than the one you are supposed to pass. Of course this is my understanding, I might be wrong here, But I think this is what’s happening. Also yes `struct {}` is invoking a type.

---

<div class="post-metadata">

**Author:** ![ge47sil](https://ziggit.dev/letter_avatar_proxy/v4/letter/g/74df32/32.png) [@ge47sil](https://ziggit.dev/u/ge47sil)\
**Post date:** [July 27, 2024, 9:29am UTC](https://ziggit.dev/t/types-in-zig/5382/3 "2024-07-27T09:29:51Z")

</div>

Edit: While I was writing, I guess I answered my own questions, which might be the reason why there is not really a question in this statement.

Yes. That it fails was also my intention. Currently I am wondering what is the way to define a type. As in my example I have a function that takes to compile time parameters and returns a type, yet I return a struct that should describe the type, but it seems the type is described by the function call with the 2 compile time parameters.

What I am trying to understand is what is the underlining concept of types in zig? At first I thought it was a struct because we also have something like:

```zig
pub const Foo = struct {
   ...
};

```

Where here Foo describes the struct and where I can reference it later to say this is the struct I want to work with. In C, this would be something like this:

```zig
struct Bra {
   ...
};

```

or

```zig
typedef struct {
   ...
} Bra ;

```

In the end a struct is just some packing of data, and in zig we can associate some function to it, so we have a better programming experience.

But if we introduce types (or kinda generics) to this, what a struct is changes in some sense.

When I change this:

```zig
fn F(T: type, comptime i: usize) type {
    return struct {
        const Self = @This();
        const a: usize = i;
        const b: usize = 1337;

        fn init() Self {
            return Self{};
        }

        fn g(self: Self) usize {
            _ = self;
            return a;
        }

        fn bra(self: Self, o: Self, t: T) void {
            std.debug.print("self: {} other: {} , {}\n", .{ self.g(), o.g(), t });
        }
    };
}

```

to:

```zig
fn F(T: type, comptime i: usize) type {
    _ = i;
    return struct {
        const Self = @This();
        const b: usize = 1337;

        fn init() Self {
            return Self{};
        }

        fn g(self: Self) usize {
            _ = self;
            return a;
        }

        fn bra(self: Self, o: Self, t: T) void {
            std.debug.print("self: {} other: {} , {}\n", .{ self.g(), o.g(), t });
        }
    };
}

```

My example works again. So I assume that types depend on the const values of a struct and the fields?

---

<div class="post-metadata">

**Author:** ![ge47sil](https://ziggit.dev/letter_avatar_proxy/v4/letter/g/74df32/32.png) [@ge47sil](https://ziggit.dev/u/ge47sil)\
**Post date:** [July 27, 2024, 9:34am UTC](https://ziggit.dev/t/types-in-zig/5382/4 "2024-07-27T09:34:14Z")

</div>

I tried also something else and it seems like I can you this function as my own type:

```zig
fn A(T: type) type {
    return struct {
        const Self = @This();

        b: F(T, 1),

        fn init() !Self {
            return Self{ .b = F(T, 1).init() };
        }
    };
}

```

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [July 27, 2024, 9:36am UTC](https://ziggit.dev/t/types-in-zig/5382/5 "2024-07-27T09:36:02Z")

</div>

I think this post might help you a bit, understanding comptime can help understanding how the type system work

[implementation of comptime](https://ziggit.dev/t/implementation-of-comptime/5041/2)

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [July 27, 2024, 9:40am UTC](https://ziggit.dev/t/types-in-zig/5382/6 "2024-07-27T09:40:57Z")

</div>

There is also this one link I think this might help you as well 🙂  
[Types and Zig](https://matklad.github.io/2023/08/09/types-and-zig.html)

---

<div class="post-metadata">

**Author:** ![ge47sil](https://ziggit.dev/letter_avatar_proxy/v4/letter/g/74df32/32.png) [@ge47sil](https://ziggit.dev/u/ge47sil)\
**Post date:** [July 27, 2024, 9:45am UTC](https://ziggit.dev/t/types-in-zig/5382/7 "2024-07-27T09:45:00Z")

</div>

Thanks! I take a look.

---

<div class="post-metadata">

**Author:** ![Sze](https://ziggit.dev/user_avatar/ziggit.dev/sze/32/496_2.png) [@Sze](https://ziggit.dev/u/Sze)\
**Post date:** [July 27, 2024, 10:33am UTC](https://ziggit.dev/t/types-in-zig/5382/8 "2024-07-27T10:33:45Z")

</div>

> [@ge47sil](#):
>
> ```zig
> fn F(T: type, comptime i: usize) type {
> _ = i;
> return struct {
> 
> ```

> [@ge47sil](#):
>
> My example works again. So I assume that types depend on the const values of a struct and the fields?

Because `i` isn’t used within the struct, the struct type doesn’t depend on `i` which is why only `T` contributes to what parameter combination results in unique types/versions of this generic struct.

The post @pierrelgol has linked to, explains that the external dependencies are used to determine whether two types are the same. So the unused `i` has no effect, but if you use it in some way within the struct, then the two `F` calls produce different types again.
