Standard library · Randomness
random/rnd
Imported as import "random/rnd" as rnd, its names are then rnd.…. Every signature below is the one the checker infers.
Random numbers, from a generator that is a value.
PCG32 (O'Neill): a 64-bit state, a 32-bit output that passes the statistical tests, and one multiply and a few shifts a number. The generator is a Rng value — there is no hidden state — so a function that draws hands back the next generator with the number, and the same seed gives the same sequence on every run and every machine.
Not for secrets: a PCG stream can be predicted from its output. Keys and tokens come from random_i64(), which asks the operating system.
r = rnd.seed(42) (n, r) = rnd.int_in(r, 1, 7) # a die n >= 1 && n <= 6 # => true (x, r) = rnd.float(r) x >= 0.0 && x < 1.0 # => true (who, r) = rnd.pick(r, Cons("ada", Cons("bob", Nil))) who != None # => true deck = buf_int(3) r = rnd.shuffle(r, deck) # in place; the generator comes back
Types
Rng
Rng(state: Int, inc: Int)
Functions
fn seed(n: Int) -> Rng
A generator from a seed; two seeds, two streams.
(a, _) = rnd.next_int(rnd.seed(1)) (b, _) = rnd.next_int(rnd.seed(1)) a == b # => true (c, _) = rnd.next_int(rnd.seed(2)) a == c # => false
fn seed2(n: Int, stream: Int) -> Rng
(a, _) = rnd.next_int(rnd.seed2(1, 1)) (b, _) = rnd.next_int(rnd.seed2(1, 2)) a == b # => false
fn seed_from_os() -> Rng
A generator seeded by the operating system: different every run.
(a, _) = rnd.next_int(rnd.seed_from_os()) a >= 0 # => true
fn next_int(r: Rng) -> (Int, Rng)
The next 32-bit number, 0 .. 2^32 - 1, and the generator after it.
(n, r2) = rnd.next_int(rnd.seed(7)) n >= 0 && n < 4294967296 # => true
fn int_in(r: Rng, lo: Int, hi: Int) -> (Int, Rng)
A number in lo..hi, hi excluded, without the bias a % would have: a draw that lands in the ragged end of the range is taken again.
(n, _) = rnd.int_in(rnd.seed(7), 10, 20) n >= 10 && n < 20 # => true
fn float(r: Rng) -> (Float, Rng)
A float in [0, 1), 53 random bits of it.
(x, _) = rnd.float(rnd.seed(7)) x >= 0.0 && x < 1.0 # => true
fn bool(r: Rng) -> (Bool, Rng)
(b, _) = rnd.bool(rnd.seed(7)) b == true || b == false # => true
fn pick(r: Rng, xs: List('a)) -> (Option('a), Rng)
One of a list, or None of an empty one.
(x, _) = rnd.pick(rnd.seed(7), Cons("only", Nil)) x # => Some(only) (y, _) = rnd.pick(rnd.seed(7), Nil) y == None # => true
fn shuffle(r: Rng, b: Buf(Int)) -> Rng
Fisher–Yates over a buffer, in place; the generator after it.
b = buf_int(4) b[0] = 1 b[1] = 2 b[2] = 3 b[3] = 4 r = rnd.shuffle(rnd.seed(7), b) b[0] + b[1] + b[2] + b[3] # => 10
fn bytes(r: Rng, n: Int) -> (Str, Rng)
n random bytes, as a string of them.
(s, _) = rnd.bytes(rnd.seed(7), 16) #s # => 16
Tests
test_reference_streamtest_rangestest_shuffle_keeps_everything