Proposal: add a simple PRNG provider to `std.process.Init` (Zig 0.16 “juicy main”)

In Zig 0.16, we now have juicy main via std.process.Init.
This structure provides common process plumbing (I/O, allocator, environment, etc.) to make it easier to start writing programs.

I think it would also be reasonable to include a non-cryptographic PRNG provider in Init.

A very common need for new users—and for many small, quick command-line tools—is simply “I need random numbers”. Today this requires several lines of setup (OS randomness + seeding + PRNG selection), which feels heavy for simple use cases.

I am not proposing a global RNG stream, nor cryptographic randomness.
The idea is to provide a factory-style interface that returns a fast PRNG, with explicit seeding.

Proposed user-side usage

const std = @import("std");

pub fn main(init: std.process.Init) void {
    const gpa = init.gpa;
    const io = init.io;

    // Non-deterministic, OS-seeded PRNG
    var rng_os = init.rng.seedOs();

    // Deterministic, user-seeded PRNG
    const seed: u64 = 123456789;
    var rng_user = init.rng.seedUser(seed);

    _ = gpa;
    _ = io;
    _ = rng_os;
    _ = rng_user;
}

Proposed API surface (conceptual)

fn seedOs() std.Random.DefaultPrng
/// Returns a fast, non-cryptographic PRNG seeded from the operating system
/// (Unix / Windows). Intended for convenience and general use.
/// For reproducibility or custom RNGs, use std.Random directly.

fn seedUser(seed: u64) std.Random.DefaultPrng
/// Returns a fast, non-cryptographic PRNG seeded with the provided value.

Rationale

  • RNG usage is extremely common in small tools and early experiments.
  • This removes boilerplate without hiding policy: seeding is explicit.
  • Returning a PRNG instance (not a shared stream) avoids hidden coupling.
  • Advanced users can ignore this entirely and use std.Random as today.

Question

Would something like this be appropriate to include in std.process.Init, or does it conflict with Zig’s intent for Init as process plumbing?

5 Likes

Not what you ask for, but on a related note - init gives you Io which recently has gained random and randomSecure functions

Given how often I’ve seen prng’s used where cprng’s should’ve been used, I’d hope that the latter is at least as easy to obtain as the former.

16 Likes

:wink:

pub fn xorshift32(in_x: u32) u32 {
    var x = in_x;
    x ^= x << 13;
    x ^= x >> 17;
    x ^= x << 5;
    return x;
}

(but seriously, this is my go to random number generator ever since I learned about it)

3 Likes

you already get an Io from Init, and Io.random() exists. Zig Documentation

Is this different from that?

1 Like

Went to give this a try, but it hasn’t landed in the latest master build available through the zig site yet. Too bleeding edge for now :smiley:

One of many benefits of building Zig from source :wink:

1 Like