Skip to content

Stdlib proposal: "Overridable methods" should be namespaced #26017

@lipfangmoe

Description

@lipfangmoe

I had previously made a Ziggit post about this, and I wish I would've gotten a bit more feedback before making a more formal proposal, but for now this will have to do!

There are a few places in the Zig Standard Library where a pattern of an "overridable method" is used. The ones I personally use most often are format, and the json* (jsonParse/jsonParseFromValue/jsonStringify)

However, I do have one big gripe still. Namely, it can often be extremely frustrating to write reusable (de)serializers. One use-case I have for reusable serializations is Packed Flag structs, which should be parsed and stringified as integers. So I'll need to implement the format, jsonStringify, jsonParse, and jsonParseFromValue methods for each case:

pub const MyBitFlags = packed struct {
    foo: bool = false,
    bar: bool = false,
    baz: bool = false,

    const Mixin = PackedFlagsMixin(@This());
    pub const format = Mixin.format;
    pub const jsonStringify = Mixin.jsonStringify;
    pub const jsonParse = Mixin.jsonParse;
    pub const jsonParseFromValue = Mixin.jsonParseFromValue;
}

However, this gets extremely verbose to write over and over again, especially considering the old solution was a single line: pub usingnamespace PackedFlagsMixin(@This());

Namespacing is good, actually

This is of course the reasoning behind removing usingnamespace in the first place! And it's a good reason. However, because the standard library doesn't namespace overridable serialization methods, so there was no great alternative to mixins for those cases (besides writing a line for each specific method you want to override).

A good solution could be to put serialization methods in a namespace. For instance:

pub const MyBitFlags = packed struct {
    foo: bool = false,
    bar: bool = false,
    baz: bool = false,

    pub const Fmt = PackedFlagsFmt(@This());
    pub const Json = PackedFlagsJson(@This());
}

And then fmt would look for T.Fmt.format instead of T.format, and json would look for T.Json.parse instead of T.jsonParse.

Another related option would be a "standard" namespace (i.e. Mixins), so that a single mixin could be used to define all overridable behaviors, similar to what we had before with usingnamespace:

pub const MyBitFlags = packed struct {
    foo: bool = false,
    bar: bool = false,
    baz: bool = false,

    pub const Mixins = PackedFlagsMixin(@This());
}

In this case, fmt would look for T.Mixins.format, and json would look for T.Mixins.jsonParse.

Feedback welcome!

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions