1. 56
  1. 32

    I personally enjoy the way how Zig modules and macros are implemented. It feels very elegant to see existing language features being reused to achieve more functionality.

    This is the biggest thing for me. In C & Rust, once you want to do something sufficiently complex with types, you have to break out into a “meta language” that runs somewhere in the middle of parsing. Control flow in these macro languages comes with different syntax and semantics. In Zig, these are the same thing. inline while works at comptime and runtime. Comptime reflection uses the same syntax! This made prototyping with complex type manipulation very quick compared to my experiences with C / Rust.

    1. 4

      I’m a little confused by this statement:

      Zig runtime is very bare-bones: no GC, no utilities for HTTP or JSON, even no way to concatenate strings! But this also implies that most minimal Zig programs can remain small.

      The frontpage for Zig has an example parsing some JSON from the standard library. I feel like there’s an important distinction between the standard library and the runtime that I’m missing. Can anyone provide any more context?

      1. 5

        Yeah that isn’t the most clear statement. While the standard library may have JSON and other utilities, it isn’t part of the final binary unless you use it. Compared to something like Go, where you have the garbage collector included in the output executable file. (Though I’m not sure of any compiled language that would include an http server if you don’t need it, I guess it might exist?)

      2. 3

        // Single-line comments start with “//”, documentation comments start with “///”

        What is a documentation comment? Or rather, what is a non-documentation comment?

        1. 14

          To expand on zie’s answer, in Rust (I don’t use Zig but Rust works the same way), this code:

          // mod.rs
          //! This is a module level documentation comment.
          // This is not, it's just a regular comment.
          
          /// This is a documentation comment for the function
          // This isn't, it's just a regular comment (TODO: refactor this garbage)
          pub fn frobulate(foo: usize) -> usize {
            foo & 0xf00
          }
          

          Would, using the rustdoc tool, generate HTML documentation like this, but fancier:

          mod

          This is a module-level documentation comment.

          frobulate(foo: usize) -> usize

          This is a documentation comment for the function.

          There’s some other cool things too, like you can embed markdown code blocks containing example code, which will be both embedded in the documentation and automatically tested as part of your test suite to make sure they don’t fall out of date.

          It’s pretty similar to Javadocs or Sphinx in Python, if you’ve used those, just easier to use IMO.

          1. 4

            Zig has tooling to pull comments and put those in their documentation. It’s not yet fully fleshed out(last I looked), but I imagine they will get around to it eventually. I’m typing this from memory and I might be wrong, but I believe the current doc code is currently something like: if it starts with /// pull it in and treat it like markdown for documentation on this code.

            Python does similar things, but doesn’t mark it special, just where it is in the code is what makes it a doc comment. i.e. “”” right after a def is documentation for that function.

            non-doc comments are completely ignored.

            1. 2

              Oh dear; that’s a tremendous red flag to conflate “documentation” with “html files extracted from comments”. Nope nope nope.

              https://stevelosh.com/blog/2013/09/teach-dont-tell/

              1. 22

                Ideally, your software project should have four kinds of documentation: tutorials, how-to guides, technical explanations, and technical reference material. https://diataxis.fr/

                Docstrings in source code are a good way of representing reference material, for answering the question: here’s the name of a function, now what does it do? So it’s good that Zig supports docstrings in its tooling. You still need the three other kinds of documentation if you want to have great documentation.

                1. 5

                  They can also be nice when your editor shows you information about a function using LSP.

                  1. 1

                    I see; I may have been misreading the explanation. At first it sounded to me like they’re called “documentation comments” because that’s where the documentation comes from, but that may have not been what was meant. I agree docstrings are useful for reference specifically. (but I’ve only even used them in the context of a repl)

                    1. 2

                      Docstrings to HTML, basically.

                      Like Codox for Clojure or LDoc for Lua.

                  2. 17

                    Zig is hardly alone in doing this. Zig has documentation outside of the source files also.

                    I think the main purpose is to document the function calls themselves and to extract those into something hopefully easier to use than: go read the source comments.

                    Your link basically says this: “Again, docstrings are great once you know the project.”

                    Using a special string like /// hopes to alleviate this issue your link talks about: “Auto-generated documentation has no coherent voice. It pulls in everything in the code without regard for overall structure and vision.”

                    With ///, the goal is to help alleviate that problem. How well it does that(both now and what is possible) is certainly up for debate.

                    Also, while I basically agree with what’s said in that link, I find they way they present the information to be terrible, but that’s a personal and not a universal perspective. Documentation and teaching is HARD and is not universal in any way shape or form.

              2. 1

                The hello world example compiles to 200-300k binary after stripping, what am I doing wrong?

                edit: Seems like -OReleaseSmall is the key. Neat!

                1. 1

                  Zig will make a great SML target (or any language target for that matter) :)

                  1. 16

                    Zig might be good for language runtimes. I noticed that the Roc compiler is written in Rust, but the runtime is written in Zig. From the Roc FAQ:

                    Roc’s standard library was briefly written in Rust, but was soon rewritten in Zig.

                    • We struggled to get Rust to emit LLVM bitcode in the format we needed, which is important so that LLVM can do whole-program optimizations across the standard library and compiled application.
                    • Since the standard library has to interact with raw generated machine code (or LLVM bitcode), the Rust code unavoidably needed unsafe annotations all over the place. This made one of Rust’s biggest selling points inapplicable in this particular use case.
                    • Given that Rust’s main selling points are inapplicable (its package ecosystem being another), Zig’s much faster compile times are a welcome benefit.
                    • Zig has more tools for working in a memory-unsafe environment, such as reporting memory leaks in tests. These have been helpful in finding bugs that are out of scope for safe Rust.
                    1. 1

                      Could be, but it seems like you need a significant runtime for strings, GC, and even integers and floats most likely