#How to do Generics "like this"

1 messages · Page 1 of 1 (latest)

gloomy monolith
#
pub const Tokenizer = struct {
    buffer: [:0]const u8,
    index: usize,
    t: type,

    pub fn new(buffer: [:0]const u8, comptime t: type) Tokenizer {
        return .{
            .buffer = buffer,
            .index = if (std.mem.startsWith(u8, buffer, "\xEF\xBB\xBF")) 3 else 0,
            .t = t,
        };
    }
    const State = enum {
        start,
        invalid,
        identifier,
    };

    pub fn next(self: *Tokenizer) type {
        var result: self.t = .{
            .tag = undefined,
            .loc = .{
                .start = self.index,
                .end = undefined,
            },
        };

Im getting

test
└─ run test
   └─ zig test Debug native 1 errors
src/libs/token/root.zig:100:43: error: expected type 'datatok.build()', found 'root.Tokenizer'
    var tokenizer: DataTag = Tokenizer.new("frame", DataTag);
                             ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
src/libs/token/root.zig:13:23: note: struct declared here
pub const Tokenizer = struct {
                      ^~~~~~
src/libs/token/datatok.zig:14:12: note: enum declared here
    return @Type(.{ .@"enum" = .{
           ^~~~~

DataTag is a comptime type combining my shared tags, and the data tags

I'm running the test with this

test "get keyword tokenized" {
    var tokenizer: DataTag = Tokenizer.new("frame", DataTag);
    try testing.expect(tokenizer.next() == DataTag.keyword_frame);
}
silver hawk
#

In zig generics are functions that return types, so you can do:

pub fn Tokenizer(T: type) type {
  return struct {
    buffer: [:0]const u8,
    index: usize,

    pub fn init(buffer: [:0]const u8) @This() {
        return .{
            .buffer = buffer,
            .index = if (std.mem.startsWith(u8, buffer, "\xEF\xBB\xBF")) 3 else 0,
        };
    }

    const State = enum {
        start,
        invalid,
        identifier,
    };

    pub fn next(self: *@This()) T {
        var result: T = .{
            .tag = undefined,
            .loc = .{
                .start = self.index,
                .end = undefined,
            },
        };
        // ...
    }
  };
}
#

then you use it like:

var tokenizer: Tokenizer(DataTag) = .init("frame");
try testing.expect(tokenizer.next() == .keyword_frame);
gloomy monolith
#

oh that is not how i expected that to work at all

#

Can i do Tokenizer(DataTag).init("frame"); for normal human activities?

silver hawk
#

both is fine

gloomy monolith
#

k ill stick with the normal human approach 🙂

silver hawk
#

above is just using decl literals

gloomy monolith
#

Very helpful thank you!

silver hawk
gloomy monolith
#

you changed my new to init did you grab that from your own language or is it just prefered to use init?

silver hawk
#

zig std uses init

#

new or create makes it sound like the function allocates to heap and returns the address

gloomy monolith
#

ahh, my T is wrong

#

T is the Tag, but it needs to be the Token

#

alright made all those adjustments, I have a different question, do i do a new help zig-help question?