Zig is a language that requires flexibility. While using Zig, I was fascinated by its powerful features and did some in-depth research into what it could do, and found that it was possible to freely define and implement complex generic types at the programming level. And after many attempts to extend that feature into a tool that could be used practically, I was able to reach a conclusion.
Zig’s powerful compile-time generics are ‘an airplane can fly and turn into a jet or a spaceship, but to do so, you have to climb on top of the airplane and manually hammer and weld it.’
I thought about why it came to that. The reason was Zig’s exclusive embrace of abstraction. I know that Zig is not an object-oriented programming language. However, Zig’s compile-time generics imply some degree of object-orientation. In order for this feature to truly be powerful, an open attitude toward abstraction is needed. Zig tries to be simple and explicit. However, attempts to be explicit are counterproductive and counter-abstract. Think about it carefully. Abstracting something complex makes it simple. However, abstracting it is not explicit. Zig aims to be abstract and semi-abstract.
I want to be able to do more with Zig. However, I also want to eliminate the inconveniences that Zig is used for and that occur when collaborating on projects. After thinking about this, I think that if we restrict all the problems that occur while writing code or collaborating, the functionality will inevitably be weakened. Currently, Zig cannot prevent all problems, but I think it is a form that places restrictions on the grammar according to Zig’s design philosophy to partially solve important problems. I think Zig’s design is excellent. And if it maintains its appearance and embraces object-orientation and abstraction, I think Zig will become irreplaceable.
lib.zig:
const std = @import("std");
const Button = @import("./button.zig").Button;
const Text = @import("./text.zig").Text;
pub fn main() !void {
const b = Button(Text(void)) {
.child = .{
.inside = .{
.child = .{
.text = "button1",
},
},
},
};
try b.build();
}
widget.zig:
pub fn Widget(comptime T: type) type {
return struct {
child: T = T {},
const Self = @This();
pub fn build(self: Self) !void {
try self.child.build();
}
};
}
button.zig:
const Widget = @import("./widget.zig").Widget;
pub fn Button(comptime T: type) type {
return Widget(struct {
inside: T = T {},
const Self = @This();
pub fn build(self: Self) !void {
_ = self;
}
});
}
text.zig:
const Widget = @import("./widget.zig").Widget;
pub fn Text(comptime T: type) type {
return Widget(struct {
inside: T = T {},
text: []const u8 = "",
const Self = @This();
});
}