# Code Patterns

**URL:** <https://ziggit.dev/t/code-patterns/1748>\
**Category:** Docs\
**Tags:** language, standard-library, zig-0-15-2\
**Created:** [September 14, 2023, 8:33pm UTC](https://ziggit.dev/t/code-patterns/1748 "2023-09-14T20:33:59Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [September 14, 2023, 8:34pm UTC](https://ziggit.dev/t/code-patterns/1748/1 "2023-09-14T20:34:00Z")

</div>

Code patterns listed here are either consistently recurring source code snippets from the [Zig Standard Library (0.15.2)](https://ziglang.org/documentation/0.15.2/std/) or lesser known language construct usage examples from the [Zig Language Reference (0.15.2)](https://ziglang.org/documentation/0.15.2/).

* * *

## I. Syntax

- [Closure](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Thread/Pool.zig#L110-L128)

- [Context](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/hash_map.zig#L128-L134)

- [File Structs](https://ziglang.org/documentation/0.15.2/#Source-File-Structs)

- [Pointer Size](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/elf.zig#L1034)

- [Decl Literals](https://ziglang.org/download/0.14.0/release-notes.html#Decl-Literals)

- [Default Arguments](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/heap/memory_pool.zig#L26-L33)

- [@enumFromString](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/enums.zig#L182)

- [Side Computation Block](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/fs/path.zig#L88-L105)

- [Destructuring Assignment](https://ziglang.org/documentation/0.15.2/#Destructuring)

- [Hashed Mappings Storage](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/zig/llvm/Builder.zig#L20)

- [Module-wide Overridable Options](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/std.zig#L112-L115)

- [Self-referential Type Alias](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/enums.zig#L290-L291) ([Anti-pattern Counterpart](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/tar.zig#L500-L504))

- [Variable Struct Initialization](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Thread/Mutex/Recursive.zig#L20) ([Anti-pattern Counterpart](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Thread/Mutex.zig#L212))

- [Return Value Struct Initialization](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/array_hash_map.zig#L142) ([Anti-pattern Counterpart](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/array_hash_map.zig#L1037))

* * *

## II. Polymorphism

- [Duck Typing](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/mem.zig#L603)

- [Generic Type](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/hash_map.zig#L135-L140)

- [Generic Function](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/mem.zig#L1194)

- [Basic Type Formatting](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Io/Writer.zig#L566-L588)

- [Custom Type Formatting](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/SemanticVersion.zig#L153-L157)

- [Custom Type JSON Formatting](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/json/hashmap.zig#L10)

- [Compile-time Implementation Switching](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/posix.zig#L44-L57)

- [Dynamic Dispatch (Fat Struct or Pointer)](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/mem/Allocator.zig#L19-L20)

- [Static Dispatch (Tagged or Discriminated Union)](https://codeberg.org/ziglang/zig/src/tag/0.15.2/doc/langref/test_inline_switch_union_tag.zig#L10-L19)

* * *

## III. Safety

- [Diagnostics](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Target/Query.zig#L183-L209)

- [Enum Index](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Progress.zig#L157-L163)

- [Error Payloads](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/tar.zig#L35-L52)

- [Compile-time Assertion](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Progress.zig#L1437)

- [Granular Error Handling](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/fuzzer.zig#L426-L430)

- [Deallocated Memory Poisoning](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/array_list.zig#L656)

- [Deferred Resource Deinitialization](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Thread/Mutex.zig#L256-L257)

- [Error-deferred Resource Deinitialization](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/buf_map.zig#L48-L49)

- [Compile-time Unreachable Switch Prong](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/math.zig#L619)

- [Compile-time Subsequent Error Absence Guarantee](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/process/Child.zig#L667)

* * *

## IV. Performance

- [Big Struct Constant Pointer Passing](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Uri.zig#L283)

- [Big Struct Constant Pointer Capturing](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/Build/Module.zig#L592)

* * *

## V. Workarounds

- [Inlined Loop with Runtime Logic (Slice Mutation or Control Flow)](https://codeberg.org/ziglang/zig/src/tag/0.15.2/lib/std/simd.zig#L204-L208)

* * *

---

<div class="post-metadata">

**Author:** ![jcollie](https://ziggit.dev/user_avatar/ziggit.dev/jcollie/32/980_2.png) [@jcollie](https://ziggit.dev/u/jcollie)\
**Post date:** [September 14, 2023, 9:30pm UTC](https://ziggit.dev/t/code-patterns/1748/2 "2023-09-14T21:30:06Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [March 5, 2025, 10:03am UTC](https://ziggit.dev/t/code-patterns/1748/3 "2025-03-05T10:03:27Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [April 3, 2025, 6:27pm UTC](https://ziggit.dev/t/code-patterns/1748/4 "2025-04-03T18:27:59Z")

</div>

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:

```zig
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")});
}

```

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [July 17, 2025, 8:09pm UTC](https://ziggit.dev/t/code-patterns/1748/5 "2025-07-17T20:09:10Z")

</div>

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

```plaintext
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?

---

<div class="post-metadata">

**Author:** ![pachde](https://ziggit.dev/user_avatar/ziggit.dev/pachde/32/2485_2.png) [@pachde](https://ziggit.dev/u/pachde)\
**Post date:** [July 17, 2025, 9:32pm UTC](https://ziggit.dev/t/code-patterns/1748/6 "2025-07-17T21:32:45Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ww520](https://ziggit.dev/letter_avatar_proxy/v4/letter/w/c2a13f/32.png) [@ww520](https://ziggit.dev/u/ww520)\
**Post date:** [July 17, 2025, 10:48pm UTC](https://ziggit.dev/t/code-patterns/1748/7 "2025-07-17T22:48:13Z")

</div>

That’s an awesome list. Thanks!

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

---

<div class="post-metadata">

**Author:** ![Sze](https://ziggit.dev/user_avatar/ziggit.dev/sze/32/496_2.png) [@Sze](https://ziggit.dev/u/Sze)\
**Post date:** [July 17, 2025, 10:54pm UTC](https://ziggit.dev/t/code-patterns/1748/8 "2025-07-17T22:54:21Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [August 20, 2025, 6:09am UTC](https://ziggit.dev/t/code-patterns/1748/9 "2025-08-20T06:09:40Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [August 21, 2025, 7:06am UTC](https://ziggit.dev/t/code-patterns/1748/10 "2025-08-21T07:06:00Z")

</div>

> [@npc1054657282](#):
>
> Hi, I’m a bit confused about the naming of the “Context” pattern here. In the zig documentation, it says:
> 
> ```zig
> Avoid these words in type names:
> 
> Value
> Data
> Context
> Manager
> utils, misc, or somebody's initials
> 
> ```

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.

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [August 21, 2025, 9:23am UTC](https://ziggit.dev/t/code-patterns/1748/11 "2025-08-21T09:23:10Z")

</div>

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`.
