Zig, Rust, and Other Languages
Language designers and developers weigh trade-offs between emerging systems languages like Zig, Rust, Nim, Odin, and more established ecosystems. Key themes include how memory allocation and string handling should signal safety guarantees (e.g., UTF‑8 validity, hidden allocations), as well as whether a language should ship with a large, batteries-included standard library or rely on third‑party packages and external package managers. Participants also debate central package repositories, dependency bloat, and how much stability and backward compatibility a “mature” language’s core libraries should promise.
Zig’s allocation model and “no hidden allocations”
- Several comments dispute the article’s strong claim that Zig avoids hidden allocations.
- Standard C functions mostly do not allocate;
strdupis a notable exception. - In Zig, most stdlib APIs follow the “pass an allocator if this might allocate” convention, but not all:
std.Thread.spawnallocates (stack + heap for argument payload) without an explicit allocator.std.ArrayListstores an allocator internally, so method calls can allocate even when no allocator is passed.ArrayListUnmanagedexists to keep allocators at a higher level and make allocations explicit.
- Some argue this is “just a convention” rather than a strict guarantee; others say that’s still valuable.
Memory management trade‑offs across languages
- Nim is highlighted as a systems language with configurable memory management; default ARC is seen as more ergonomic than threading allocators through Zig code.
- Counterpoint: one can use a global allocator or attach allocators to objects in Zig to avoid excessive plumbing.
- Odin, C with good APIs and arenas, and others are cited to argue that API design matters more than language per se.
Standard library size vs ecosystem fragmentation
- One camp prefers compact stdlibs to avoid C++‑style bloat, enable faster evolution, and reduce long‑term maintenance of obsolete APIs.
- Another camp argues small stdlibs force reliance on many third‑party packages, leading to fragmentation, multiple competing libraries, and dependency hell.
- Examples:
- Python: large stdlib is generally seen as positive, though some modules are outdated; popular third‑party libs (e.g., HTTP clients) still win on ergonomics.
- Go: praised stdlib but specific parts (logging, flags, earlier
net.IP) are criticized; newer abstractions likenetipimprove things. - Rust: absence of compression in stdlib is defended as keeping evolving domains in crates; others point to good compressors in other ecosystems’ stdlibs as counter‑evidence.
- Suggested compromise: small core stdlib + officially maintained “blessed” packages, or later adoption of de‑facto standards.
Package managers and dependency concerns
- Zig’s package story:
- Has package management via
build.zig.zonand git references; upcoming 0.12 improvements are anticipated. - No central package repository by design (similar to Go); some see this as safer, others as a bad decision.
- Has package management via
- General concerns:
- Multiple competing C/C++ package managers (vcpkg, conan, etc.) don’t interoperate well.
- Rust’s
cargo:- Avoids per‑project duplication of sources; dead code elimination mitigates binary bloat.
- Problems cited: large caches and stale incremental artifacts; upcoming automatic cache GC on nightly is welcomed.
- Some suggest using Nix instead of language‑specific managers.
Strings, Unicode, and type‑system guarantees
- Zig:
- Uses
[]const u8for strings; by convention these are UTF‑8. - Functions often assume valid UTF‑8 without runtime checks; responsibility lies with the producer.
- Critics liken this to “just don’t write bugs” and argue for encoding invariants in types.
- Uses
- Rust:
- Distinguishes
String(owned UTF‑8) and&str(borrowed UTF‑8), with runtime UTF‑8 validation in safe code. - Unsafe constructors allow skipping checks only when the programmer promises validity.
- Separate types like
OsStringavoid forcing UTF‑8 where it’s not guaranteed. - This model is praised for safety and flexibility but criticized for complexity and learning overhead.
- Distinguishes
- Go and others:
- Go
stringis “just bytes”; can hold arbitrary data, not guaranteed UTF‑8.
- Go
- Unicode support:
- Zig’s
std.unicodecovers validation and codepoint iteration; more advanced support (graphemes, categories) is in external libraries. - Similar gaps exist in Rust and Go; full Unicode handling (e.g., grapheme iteration, locale‑aware sorting) is complex and often pushed to libraries.
- Zig’s
- Some argue that because “string” requirements are so varied (mutability, slicing, Unicode semantics, performance), it’s natural that ecosystems grow multiple string abstractions despite a built‑in type.