Suggested areas for documentation improvements

Suggesting a couple of areas where documentation could be improved. I’m fully realizing that docs are considered in flux as the language changes, but thought feedback is welcome regardless.

  1. More prominent linking from Documentation - The Zig Programming Language to the standard library reference.

  2. Comptime and comptime reflection: builtins associated with comptime are documented under the Builtin Functions, but IMO this format is not adequate when writing code that inspects types. You can kind of get an idea of what functions can work on types, but when writing actual code, most likely you’ll need to look up the details from the std library source code. ZLS doesn’t seem to handle type infos very well (at least the version I use), so it doesn’t help here much either. I’d find it easier to browse the type-related built-ins in some sort of HTML format rather than code.

  3. std.json module could do with some end-to-end examples on how to use it. I was happy to notice that it recently added diagnostics (you can see line/column info for parse errors), and I can use it with a scanner when calling std.json.parseFromTokenSource. However, I guess I can’t get diagnostics if I use std.json.parseFromSlice since the scanner is internal. The parse API also had changed how tagged unions are now handled (github issue), breaking my existing code. So I started switching to using parseFromValue instead as I can override “JSON → Zig value” mapping by defining jsonParseFromValue on my type. I succeeded in doing this but it’s not very clear from the docs how to do this. Again, I seem to lose diagnostics if I use parseFromValue so I have no idea which node in my input JSON had a problem if the input doesn’t map to my types. There’s also a jsonParse function that I can attach to my types which would be called when parsing through std.json.parseFromTokenSource but I have no idea how to use it.

I guess my 3rd point is half-rant, half docs feedback, but I find this module a little hard to use. I think good end to end examples in the std.json docs would go a long way to make it more approachable and teach users of this library the idiomatic way to use it.

IMO the “lack of interfaces” in the core language may also make exploring API’s such as std.json a bit harder as hooks like jsonParse and jsonParseFromValue are not present in the top-level functions or their types.

In terms of your 3rd point, are you referring to this page? Documentation - Zig

If not disregard this point…

In regards to examples, I think it’s important to note that this documentation is auto-generated which has a few pros and cons. On the pro side, it will stay current with the implementation if the doc-comments are updated as well, meaning that it only has to be updated in one place.

More to your point though - this also means these aren’t “example driven” documents. They certainly chart the technical specification, but some functions just simply have no description as they don’t have a related comment in the source code.

At some point, it would probably be worth supplementing this documentation with more direct examples in general (including your concerns, although I haven’t looked into the json section yet). Even though cppreference is a very unapproachable website from a readability standpoint, they still have quite a few examples per page that give the user a quick idea about how to use stuff. That said, it would be additional effort to keep up the documentation apart from what is already auto-generated.

Just my two cents.

Yes, the standard library API reference. I don’t think I’ve seen the std.json module documented elsewhere.

I used to do a fair bit of Haskell coding in the past and in the Haskell community, people are often recommended to “just follow the types” when they’re trying to learn how to use some new library. I was never good at “just following the types”, I’m much more productive if I can start with some example code that already compiles and does something.

I think it’s a problem in many languages that it’s often easier to write a blog post or a gist with some code examples, but very often these don’t end up in the actual reference documentation.

2 Likes

I think a major development in programming language documentation has been the inclusion of sample code within the documentation and having those samples run as part of the tests. This ensures that the documentation (at least the samples) stay updated as the code evolves, while at the same time showing the user how to do things. I think Zig’s tests could be a natural fit for this, maybe you could mark a test as a sample in some way, telling the doc generator to include it in the docs.

/// This is how you get the nth Fibonacci number
test "[example] get nth fibonacci" {
    const n = 1;
    const nth_fib = fib(n);
    std.testing.assertEqual(@as(usize, 0), nth_fib);
}

Here the [example] would be the marker.

6 Likes

The best documentation I’ve seen is Android, almost all public functions have some doc-comment, and the more complicated ones sometimes have 200+ lines of doc-comments explaining the usage, and documenting the edge cases.

I honestly think that’s a great idea. I was thinking about that writing some more tests cases here - it’s a lot of use cases that have to directly prove correctness. I wonder what it would take to do this?

There is one thing to consider though - I think a good thing about Zig (up to this point) is the readability of the standard library. Maybe instead we should just make it a point of importance that Zig developers should feel comfortable just reading the standard itself (and there in-lies those test cases). I think there is a long standing hesitancy from reading library code because of how dense and convoluted it can be, but I haven’t had that problem thus far with Zig - quite the opposite.

2 Likes

Yeah, no argument from me that hyper-verbosity can be as opaque as saying nothing at all. I think what @dude_the_builder and myself were referring to were executable snippets that just demonstrate the code in use. Again, cppreference does this and that was probably the better part of that website until fluency in standard-ese sets in.

1 Like

Same here with my experience reading the Zig source ocde directly. At first I was a little weary, coming from languages where the source is unreadable and docs are the only way to learn things. But soon I was pleasantly surprised as to how easy the Zig source reads. Now I find myself going straight to the source code and then moving to the docs if I don’t find what I’m looking for.

1 Like

I also dive right into std library source quite often. Especially when I’m in VSCode and can jump directly into symbol definitions. But it depends on which module I’m looking at. Sometimes the test source is all I need to get going, and that’s great! But some modules, such as std.json, is split into many source files and just browsing through it on GitHub is a little tedious as there’s apparently no way to follow symbols to declaration in the GitHub GUI.

A well-formatted API reference can have an advantage over browsing source directly, as it can be edited to focus on the main usage of the library.

2 Likes

I don’t have a huge issue with “follow the types”, but for that I’d like to have better “backwards” search/index available. For example if I have found a thing I need, I’d like to get a quick reading which functions return the thing.

I think the Guides feature could be used to create some high-level documentation with explanations and examples (maybe including @dude_the_builder’s idea of marked test case examples), I think that would address the 2nd and 3rd point.

Your 1st point also sounds good, but I haven’t thought enough about it enough.
I think one example is, to be aware that there are a bunch of useful functions in std.meta that help you avoid having to repeatedly come up with your own replicas of those (and probably there are similar cases).

But the other suggestions about reading the standard library source, also help in finding these shortcuts.


Thinking more about your 1st point I almost would want a specially styled link style (maybe in some other color than blue) that links to things in the standard library that are related to the section in the language reference. Or maybe each section could have an optional block of references to the standard library.

For example the Tagged Union section and @unionInit builtin would link to:
std:meta.Tag
std:meta.TagPayload
std:meta.TagPayloadByName

Showing/hiding these references might be nice too.

3 Likes

Looking at the language reference:

Introduction

Often the most efficient way to learn something new is to see examples, so this documentation shows how to use each of Zig’s features.

Zig Standard Library

Zig’s Standard Library contains commonly used algorithms, data structures, and definitions to help you build programs or libraries. You will see many examples of Zig’s Standard Library used in this documentation.

I think one good first step would be to create additional tests that serve as examples for things that currently aren’t really explained. For example @unionInit could use an example test that illustrates how it is used and also show off the useful std.meta functions.

While thinking along those lines, what if the tests that are in the reference would actually link to the standard library (so the code would be clickable), however it would be important that this doesn’t make the code awkward to copy. Similar to how the Racket documentation cross references all the things, even in code examples: 2.3 Lists, Iteration, and Recursion

This is probably not easy to implement (racket updates some documentation index-ing structure every time you build documentation), but from a user standpoint it is one of the things I have appreciated a lot about Racket’s documentation.

1 Like

Wow that Racket docs feature is impressive!

1 Like

Sorry I’m arriving to this discussion a bit late. I’m going to give some info instead of replying point by point to each comment:

  • For 0.12 we plan to merge language reference and stdlib docs into a single thing by turning the langref into a guide. We also plan to add in the same release a second guide that explains how to use the build system to solve common use cases, and probably more in the future.

  • Zig has a way of marking a test as a end-to-end “how to” test (called doctest). This is the syntax:

pub const MyType = struct {
   // ...
};

test MyType {
   // how to use MyType, will be displayed in autodoc
}

test "mytype is not borked" {
   // this is a normal test that won't show up in autodoc
}

And in fact std.json does have a few doctests (see bottom of the page): Documentation - Zig

6 Likes

So to be clear the test MyType... will show up in the autodoc and run as part of the usual tests? That’s great!

yes, it’s a normal test wrt zig test and the fact that it refers to a decl directly (instead of having a string name) marks is as documentation for autodoc.

if you click the autodoc link I shared above you will see that std.json.parseSlice does have a doctest

4 Likes