Code Patterns

Code patterns listed here are either consistently recurring source code snippets from the Zig Standard Library (0.15.2) or lesser known language construct usage examples from the Zig Language Reference (0.15.2).


I. Syntax


II. Polymorphism


III. Safety


IV. Performance


V. Workarounds


79 Likes

I’ve only looked at a few of these so far but this is awesome! My only concern is that blog posts and the like have a tendency to bit rot as the language (or standard library) evolves. If these were ultimately integrated into the standard library as “testable documentation” they could evolve along with the language and standard library.

8 Likes

I’ve updated this list to contain only Zig 0.14.0 langref/stdlib patterns, except for the Decl Literals, which aren’t in the langref (yet?), so I linked the section from latest release notes.

As always, feel free to suggest any changes.

8 Likes

I’ve just found out that you can use @field instead of std.meta.stringToEnum to get an enum literal from a string at compile-time.

In fact, there’re quite a few places in the std that use this pattern. I’ve added one of those places to the list as @enumFromString.

So, here’s how you can have the “missing” builtin @enumFromString in userland:

const std = @import("std");

fn enumFromString(comptime E: type, comptime string: [:0]const u8) E {
    if (@hasField(E, string)) {
        return @field(E, string);
    }
    @compileError("Enum " ++ @typeName(E) ++ " has no field named " ++ string);
}

pub fn main() void {
    std.debug.print("{}\n", .{enumFromString(std.zig.Ast.Mode, "zig")});
}
11 Likes

Hi, I’m a bit confused about the naming of the “Context” pattern here. In the zig documentation, it says:

Avoid these words in type names:

Value
Data
Context
Manager
utils, misc, or somebody's initials

I understand that the naming of Context here is a highly generic name, and perhaps not subject to this rule. In this scenario, is Context an encouraged naming pattern?
Actually, I have to say that even in this scenario, the name Context still gives me some confusion. Perhaps a name like Policy is a better pattern name?

pattern != type

I don’t think type naming conventions need to apply to the names of patterns, which by their nature are higher-level abstractions. In the example linked for Context, it is not a specific type, but rather a type parameter. What’s missing there is a definition of “Context” which perhaps has better names for those not already familiar with the pattern, e.g. “UserData” - a parameter that the service being provided doesn’t use directly but is there as a way for user code to carry the necessary data (i.e. “context”) to fulfill a service client’s contract.

If you’re going to collect patterns, I think it would be helpful to follow the format of the Design Patterns books and provide the canonical explanatory texts before diving into example code: including basic summary, where to use it, where not to use it (anti-patterns), etc.

1 Like

That’s an awesome list. Thanks!

One question, what’s the usage of Enum index? I don’t quite understand.

1 Like

It is an index that uses an enum so that the index type has a type that is distinct from the backing type of the declared enum, in the linked example, you can’t directly pass an u8 where an Index is required.

Basically it makes it less likely that you pass some random byte and accidentally end up using it as an index. So it just adds some guard rails, by using the enum to get a distinct type.

3 Likes

Updated the list in preparation for Zig 0.15.1 and tried to group things.

The only nits are:

  • Decl Literals haven’t been added to langref, yet. So, still referencing 0.14.0 Release Notes there.
  • There’s this curious “Inlined Loop with Runtime Logic” workaround, which is in a group of its own for now.
8 Likes

Tbh I would just ignore such advice, especially in a language with namespaces. Either there’s a collision with the languages keyword or symbols (then find a different name) or there’s no collision (then your names are fine).

It smells too much like ‘Clean Code’ advice :wink:

There should be guidelines within a project to be consistent (like the stdlib), but for 3rd-party code that’s really too much to ask IMHO.

7 Likes

I believe it is arbitrary though sometimes I wish people would have just common sense.
For my work a few weeks ago I had to import a bunch of huge interrelated jsons into a database where I encountered fieldnames like:

  • targetkey
  • scheme
  • context
  • sourcekey
  • entity
  • entitybusinesscontextkey
  • contextkey
  • key

Absolutely meaningless names.

It was next to impossible to deduce what everything was (many hours of Team calls) and completely impossible to remember.

My philosophy is: call the thing by its name :slight_smile:
Probably every project needs an utils and misc or funcs.

4 Likes