Module std::rand

Randomness as an effect: code draws random numbers only through a Random capability, and fault points only through Draw, so its caller decides where the answers come from. The root supplies no Random: OsRandom draws the operating system's entropy through the root's Sys, std::sim::SimRandom is a seeded generator, and Calm answers every Draw the common way.

Source: std/rand.weir; committed interface: std/rand.iface. Index

effect Random

pub effect Random {
    fn next() -> Int;
}

A stream of random numbers; OsRandom draws them from the OS, std::sim::SimRandom deterministically from a seed.

op next

fn next() -> Int;

Control kind tail: the clause's result is the op's, and the performer goes on, never aborted or suspended.

The next number of the sequence, at least 0.

handler OsRandom

pub handler OsRandom(mut buf: [u8; 256], mut left: usize) for Random with Sys

The operating system's entropy as Random, for unpredictable numbers (a hash seed, a token, retry jitter).

Install it over the root's Sys as with OsRandom([0u8; 256], 0) { … }: each next() is eight bytes the device drew, the top bit cleared, so it is at least 0. It draws 256 bytes at a time, one system call per 32 numbers; left counts the bytes of buf not yet handed out, taken from its end, so install it empty (0); any left above 256 refills as 0 does. Natively the bytes are getrandom(2)'s, and under weir run the host's; under WEIR_DEVICE=sim, weir explore, weir test and the playground they are the simulated device's fixed stream, so a run is reproducible there and nowhere else.

Handles Random, with clauses:

effect Draw

pub effect Draw {
    fn pick(n: Int) -> Int;
    fn delay(max: Int) -> Int;
    fn fault(p: Int) -> Bool;
    fn part(n: Int) -> Int;
}

A draw whose answer the caller decides, of the shapes a simulation spends its randomness on: which of n things happens next, how long something takes, whether a rare thing (a fault) happens, and how much of n a short count moves. std::sim::Sampled answers from a seeded generator, std::sim::Searched makes each draw a weir explore choice point and bounds the faults a path takes, and Calm answers the common case, as a production run does.

op pick

fn pick(n: Int) -> Int;

Control kind tail: the clause's result is the op's, and the performer goes on, never aborted or suspended.

One of 0..n; 0 when n is 1 or less.

op delay

fn delay(max: Int) -> Int;

Control kind tail: the clause's result is the op's, and the performer goes on, never aborted or suspended.

A delay in 0..=max; 0 when max is 0 or less.

op fault

fn fault(p: Int) -> Bool;

Control kind tail: the clause's result is the op's, and the performer goes on, never aborted or suspended.

Whether the rare thing happens: sampled, p times in a hundred; never when p is 0 or less.

op part

fn part(n: Int) -> Int;

Control kind tail: the clause's result is the op's, and the performer goes on, never aborted or suspended.

A strictly short part of n > 1 things, in 1..n; 1 when n is 2 or less.

handler Calm

pub handler Calm: shared for Draw

Every draw its common answer: the first of n, no delay, no fault, the least part. Install it (with Calm { … }) to run production code that has fault points.

Handles Draw, with clauses: