Is std.fmt.Parser intended to be exported by the standard library?

std.fmt.Parser strikes me as a rather unusual type for the standard library:

  • it assumes the type for the integer type, rather than being parameterized
  • the naming of the interface methods are unusual, it looks like an iterator but not quite
  • the methods are optional where normally an error union would be used
  • the initialization is rather error prone - iter defaults to undefined but is actually required
  • it’s functionality is too specialized to be generally useful
  • there’s only a single usage in the standard library I found - parsing format strings in comptime (ref)
  • it is broken outside of comtime in 0.13.0 release (the issue)

This leads to the conclusion that the type was likely not intended to be public and exposed by the standard library.

Format strings are passed to custom implementations of .format, so it’s possibly there as an affordance for parsing them.

I would be a bit surprised, but not very surprised, if there was code in the wild which takes advantage of that. I’ve never once made use of the format string parameter, let alone parsed it, and I write a lot of custom formatters.

Still, I think it’s better for std to err on the side of making things public. It’s only harmful for internal methods which could violate invariants of a data structure if used improperly, so for types, I don’t see a good reason not to do it.

3 Likes

Why would it be parameterized? Number characters have to fit in u21, and usize is used when dealing entire numbers, not just a character. What’s there to parameterize?

It looks like a stream do me, which is what it is.

This is a philosophical point of view. The return types they have chosen look good to me. From a practical point of view, errorr are marked as cold, so if you think an error is going to happen frequently, it’s better to use optionals.

The issue has been fixed, hasn’t it?

2 Likes

The observation of the potential utility makes sense.

A couple of additional considerations would be a commitment to support the exposed interface (admittedly much less of a concern as of pre 1.0) and the quality of the standard library (consistency across the library and quality of individual components - std.fmt.Parser seems to be suboptimal in both regards).

Instead of
fn number(self: *@This()) ?usize
I would expect
fn int(comptime T: type, self: *@This()) ?T

I haven’t found a stream type that uses the same naming convention (e.g. std.net.Stream).

It’s objectively inconsistent with the rest of std.fmt parsing utilities though.

It shows exposing the type didn’t receive much consideration, hence the thread.

If we blame /lib/std/fmt.zig we can see that these types used to be internal but were made public by std: expose fmt methods and structs for parsing by RossComputerGuy · Pull Request #15651 · ziglang/zig · GitHub, with the following motivation (from the issue linked in the PR):

The purpose of this proposal is to provide standard methods for parsing std.fmt’s format strings. Exposing the various methods needed will make it possible to make std.fmt compatible formatters without having to reinvent the code. Currently, I’m looking to have this functionality so I can write formatted types in XML or JSON.

So the idea was to give third-party libraries and user code the ability to parse format strings in the same way std.fmt.format parses them.

I’m not sure how useful this is in practice (the implementation seems very tuned for Zig’s particular implementation of formatting), but that at least answers the “why?” question.

5 Likes

This is explicitly not a concern at all at this point. Not even core language features are considered stable. Anonymous struct types were just removed from master, for instance, so I needed to decorate a couple of literal struct constructors with the expected result type.

The standard library is definitely not stable and changes whenever core accepts a patch which changes it. Right this instant I’m on the Discord trying to figure out how panicking works now. :slight_smile: Par for the course!

There’s a plan to do a full audit of the standard library as preparation for 1.0. That will be the right time to get into the weeds about what stays public, or what stays at all in fact.

3 Likes

Thanks for sharing your thoughts everyone!
Here’s a tiny PR to clarify the point of the parser and fix it up a bit: Remove unused `buf` field from `std.fmt.Parser` by raindev · Pull Request #21994 · ziglang/zig · GitHub

1 Like