How much OOP is too much OOP: A question around constructors

While this is technically a solution, using anytype rules it out for me because the method signature does not describe the options. And using comptime reflection should not be necessary for something as straightforward as an options parameter.

1 Like

Agreed. Just an observation!

1 Like

Yesterday I realized that I do want to write a chain of updates for a, say, CSS-styled container like div: div.flex().bg(…).size(…) so I ended up with:

return with(div(self.allocator), self, struct {
    fn build(ctx: anytype, c: anytype) void {
        _ = c.flex()
            .bg(rgb(0x505050))
            .size(px(500.0))
            .justify_center()
            .items_center()
            ...
    }
}.build);

with the whole power of Zig:

// Generic copy-paste friendly `with` helper. Works for any element constructor.
// Why this works:
//  - `build` is generic, so `ctx` and `c` types are inferred from the call.
//  - Compile‑time checking still enforces that `c` has the methods you call.
fn with(
    element: anytype,
    ctx: anytype,
    comptime build: anytype,
) @TypeOf(element) {
    var v = element;
    @call(.auto, build, .{ ctx, &v });
    return v;
}

Yes init-blocks as workaround is what I started to use too. It works okay-ish for nested structs (or nested structs containing arrays), like here:

…but I really wish that extra ceremony wouldn’t be needed. It’s just more irrelevant noise to sift through IMHO.

2 Likes