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â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.
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.
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")});
}
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.
Thatâs an awesome list. Thanks!
One question, whatâs the usage of Enum index? I donât quite understand.
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.
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.
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 ![]()
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.
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 ![]()
Probably every project needs an utils and misc or funcs.