0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Ziglang Memo

Last updated at Posted at 2023-06-22

Interface

Pattern 1
const std = @import("std");

const Animal = union(enum) {
    cat: Cat,
    dog: Dog,

    pub fn talk(self: Animal) void {
        switch (self) {
            inline else => |case| case.talk(),
        }
    }
};

const Cat = struct {
    anger_level: usize,

    pub fn talk(self: Cat) void {
        std.debug.print("[Cat] Meow! (anger Lv {})\n", .{self.anger_level});
    }
};

const Dog = struct {
    name: []const u8,

    pub fn talk(self: Dog) void {
        std.debug.print("[Dog] I'm a {s}\n", .{self.name});
    }
};

pub fn main() !void {
    const cat = Animal{ .cat = .{ .anger_level = 100 } };
    cat.talk();
    const dog = Animal{ .dog = .{ .name = "lilly" } };
    dog.talk();

    const animals = [_]Animal{
        cat,
        dog,
    };

    for (animals) |a| {
        a.talk();
    }
}
Pattern 2
const std = @import("std");
const assert = std.debug.assert;

const Animal = struct {
    ptr: *anyopaque,
    vtab: *const VTab,

    const VTab = struct {
        talk: *const fn (ptr: *anyopaque) void,
    };

    pub fn talk(self: Animal) void {
        self.vtab.talk(self.ptr);
    }

    pub fn init(obj: anytype) Animal {
        const Ptr = @TypeOf(obj);
        const PtrInfo = @typeInfo(Ptr);
        assert(PtrInfo == .Pointer); // Must be a pointer
        assert(PtrInfo.Pointer.size == .One); // Must be a single-item pointer
        assert(@typeInfo(PtrInfo.Pointer.child) == .Struct); // Must point to a struct
        const impl = struct {
            fn talk(ptr: *anyopaque) void {
                const self: Ptr = @ptrCast(@alignCast(ptr));
                self.talk();
            }
        };
        return .{
            .ptr = obj,
            .vtab = &.{
                .talk = impl.talk,
            },
        };
    }
};

const Cat = struct {
    anger_level: usize,

    pub fn talk(self: Cat) void {
        std.debug.print("[Cat] Meow! (anger Lv {})\n", .{self.anger_level});
    }
};

const Dog = struct {
    name: []const u8,

    pub fn talk(self: Dog) void {
        std.debug.print("[Dog] I'm a {s}\n", .{self.name});
    }
};

pub fn main() !void {
    var c = Cat{ .anger_level = 100 };
    const cat = Animal.init(&c);
    cat.talk();

    var d = Dog{ .name = "lilly" };
    const dog = Animal.init(&d);
    dog.talk();

    const animals = [_]Animal{
        cat,
        dog,
    };

    for (animals) |a| {
        a.talk();
    }
}
Pattern 3
const std = @import("std");
const assert = std.debug.assert;

const Animal = struct {
    ptr: *anyopaque,

    talkFnPtr: *const fn (ptr: *anyopaque) void,

    pub fn init(obj: anytype, comptime talkFn: fn (ptr: @TypeOf(obj)) void) Animal {
        const Ptr = @TypeOf(obj);
        const PtrInfo = @typeInfo(Ptr);
        assert(PtrInfo == .Pointer); // Must be a pointer
        assert(PtrInfo.Pointer.size == .One); // Must be a single-item pointer
        assert(@typeInfo(PtrInfo.Pointer.child) == .Struct); // Must point to a struct
        const impl = struct {
            fn talk(ptr: *anyopaque) void {
                const self: Ptr = @ptrCast(@alignCast(ptr));
                talkFn(self);
            }
        };
        return .{
            .ptr = obj,
            .talkFnPtr = impl.talk,
        };
    }

    pub fn talk(self: Animal) void {
        self.talkFnPtr(self.ptr);
    }
};

const Cat = struct {
    anger_level: usize,

    pub fn talk(self: *Cat) void {
        std.debug.print("[Cat] Meow! (anger Lv {})\n", .{self.anger_level});
    }
};

const Dog = struct {
    name: []const u8,

    pub fn talk(self: *Dog) void {
        std.debug.print("[Dog] I'm a {s}\n", .{self.name});
    }
};

pub fn main() !void {
    var c = Cat{ .anger_level = 100 };
    const cat = Animal.init(&c, Cat.talk);
    cat.talk();

    var d = Dog{ .name = "lilly" };
    const dog = Animal.init(&d, Dog.talk);
    dog.talk();

    const animals = [_]Animal{
        cat,
        dog,
    };

    for (animals) |a| {
        a.talk();
    }
}
Pattern 4
const std = @import("std");
const assert = std.debug.assert;

const Animal = struct {
    talkFn: *const fn (ptr: *Animal) void,

    pub fn talk(self: *Animal) void {
        self.talkFn(self);
    }
};

const Cat = struct {
    anger_level: usize,
    parent: Animal,

    pub fn init(anger_level: usize) Cat {
        const impl = struct {
            pub fn talk(ptr: *Animal) void {
                const self: *Cat = @fieldParentPtr("parent", ptr);
                self.talk();
            }
        };
        return .{
            .anger_level = anger_level,
            .parent = .{ .talkFn = impl.talk },
        };
    }

    pub fn talk(self: *Cat) void {
        std.debug.print("[Cat] Meow! (anger Lv {})\n", .{self.anger_level});
    }
};

const Dog = struct {
    name: []const u8,
    parent: Animal,

    pub fn init(name: []const u8) Dog {
        const impl = struct {
            pub fn talk(ptr: *Animal) void {
                const self: *Dog = @fieldParentPtr("parent", ptr);
                self.talk();
            }
        };
        return .{
            .name = name,
            .parent = .{ .talkFn = impl.talk },
        };
    }

    pub fn talk(self: *Dog) void {
        std.debug.print("[Dog] I'm a {s}\n", .{self.name});
    }
};

pub fn main() !void {
    var cat = Cat.init(100);
    cat.talk();

    var dog = Dog.init("lilly");
    dog.talk();

    const animals = [_]*Animal{
        &cat.parent,
        &dog.parent,
    };

    // const animals = [_]*Animal{
    //     @constCast(&Cat.init(100).parent),
    //     @constCast(&Dog.init("lilly").parent),
    // };

    for (animals) |a| {
        a.talk();
    }
}
Pattern 5
const std = @import("std");

const Animal = struct {
    pub fn talk(self: anytype) void {
        self.talk();
    }
};

const Cat = struct {
    anger_level: usize,

    pub fn talk(self: Cat) void {
        std.debug.print("[Cat] Meow! (anger Lv {})\n", .{self.anger_level});
    }
};

const Dog = struct {
    name: []const u8,

    pub fn talk(self: Dog) void {
        std.debug.print("[Dog] I'm a {s}\n", .{self.name});
    }
};

const Panda = struct {
    // error: no field or member function named 'talk' in 't5.Panda'
    //
    // pub fn talk(_: Panda) void {
    //     std.debug.print("Hahaha!\n", .{});
    // }
};

pub fn main() !void {
    const cat = Cat{ .anger_level = 100 };
    Animal.talk(cat);
    const dog = Dog{ .name = "lilly" };
    Animal.talk(dog);
    const panda = Panda{};
    Animal.talk(panda);
}

無名関数の色々を取得

fn foo(options: anytype) void {
    inline for (@typeInfo(@TypeOf(options)).Struct.fields) |field| {
        std.debug.print("{s}: {} {}\n", .{ field.name, @field(options, field.name), field.type });
    }
}

pub fn main() !void {
    const a: u8, const b: u8 = .{ 0, 1 };
    // const a, const b = .{ @as(u8, 0), @as(u8, 1) };
    foo(.{ .a = a, .b = b });
}

Pointer

test "*const T and *T" {
    // immutable
    const x: i32 = 1234;
    const x_ptr = &x;
    try expect(@TypeOf(x_ptr) == *const i32);
    // Error
    // x_ptr.* = 5678;
    try expect(x_ptr.* == 1234);

    // mutable
    var y: i32 = 1234;
    const y_ptr = &y;
    try expect(@TypeOf(y_ptr) == *i32);
    // Ok
    y_ptr.* = 5678;
    try expect(y_ptr.* == 5678);
}

test "pointer array access" {
    var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    const ptr = &array[2];
    try expect(@TypeOf(ptr) == *u8);

    try expect(array[2] == 3);
    ptr.* += 1;
    try expect(array[2] == 4);

    // Error
    // ptr[1] = 255;

    // Ok
    const ptr2 = @ptrFromInt(*u8, @intFromPtr(ptr) + @sizeOf(u8));
    ptr2.* = 255;
    try expect(array[3] == 255);
}

test "*const [N]T and *[N]T" {
    // immutable
    const x = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    const x_ptr = &x;
    // Error
    // ptr[0] = 255;
    try expect(@TypeOf(x_ptr) == *const [10]u8);
    try expect(x[0] == 1);

    // mutable
    var y = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    const y_ptr = &y;
    // Ok
    y_ptr[0] = 255;
    try expect(@TypeOf(y_ptr) == *[10]u8);
    try expect(y[0] == 255);
}

部分的にzig fmtを無効にする

// zig fmt: off
            var arr = [_]u8{ 1, 2 };
// zig fmt: on
var arr1 = [_]u8{ 1, 2 };

Overflow

const std = @import("std");

test "@addWithOverflow" {
    const result = @addWithOverflow(@as(u8, std.math.maxInt(u8)), @as(u8, 10));
    try std.testing.expectEqual(result, .{ 9, 1 });
}

test "std.math.add" {
    const result = std.math.add(u8, std.math.maxInt(u8), 10) catch std.math.maxInt(u8);
    try std.testing.expect(result == 255);
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?