The CLI using libraries is a good example.
One could say that the concept I suggested is a variation of the diagnostics pattern.
Let’s call it “GD” for global diagnostics, and the pattern used in the standard library for JSON “LD” for local diagnostics.
LD uses specialized diagnostics for each type of possible error, with fields like eg line: u32.
GD uses a generic structure: A string map or maybe string list.
In this regard, LD is more powerful if we actually want do use this data anything else but showing it to the user or a log file. But if showing it is all we need, then the string map is probably more easy to use, since it is more generic.
With LD, as seen in the examples, usually the diagnostics struct is on the stack and has to be explicitly specified before used.
This is in line with Zig’s philosophy, but at the same time a bit tedious.
An advantage would be here that you don’t need to think about cleaning it up, unless you want to reuse it in the same function for a second call (even then you should check in the code that in case of an error all fields are written to avoid leftovers from the previous error.
With GD, there would be only exactly one global diagnostics struct, using its own private memory.
(I’m thinking of a single threaded program only).
No need to pass it explicitly to each function.
In case of an error, a function should either
- add to / adjust the diagnostics and return an error (not necessarily the same error) or
- handle/report the error (using the diagnostics) and then clear the diagnostics.
And just to be sure, also clear the diagnostics on a high level before starting the actual action.
Anyway, both patterns require that not only your own code, but also the libraries support them.
Of course, if a library supports LD, you can use it also for GD (by formatting the diagnostic data fields to name/value strings and add them to the GD info).
As a side note, I’m coming from a background of languages with exceptions (eg. Python , Java) or quite restricted exceptions (PL/SQL), and while I’m fine with using errors instead of exceptions, the fact that it’s complicated to add useful info to errors is really a pain point.
With errors I mean basically what Python class EnvironmentError means: something outside of the program’s control.
Mere programming errors eg UB don’t need additional info, they are very well shown in the debug builds, I like that.