random gives you random numbers, plainly. Three number words:
Random for a fraction between 0 and 1, RandomRange
for a floating-point number (one that can carry a fractional part) between
two bounds, and RandomInt for a whole number between two bounds.
Plus two list words: Shuffle for a random ordering, and
Sample for draws that never pick the same item twice. All of
them sit directly on the Rnd builtin — a word the engine itself
supplies — which draws evenly-spread values from the engine's own generator.
The machine is seedless by construction: there is no seed (a
starting value that fixes the sequence) to create, store, or thread through
your code. You call a word, you get a fresh random number. That's the whole
thing — and the simplicity is the point.
Deterministic machines — computers that, given the same start, always do exactly the same thing — were asked for random numbers almost as soon as they existed. The first big customers ran on chance: the Monte Carlo simulations of the atomic-bomb laboratories, which answer hard questions by running thousands of random trials. John von Neumann proposed the first widely used generator in the late 1940s, the middle-square method: square a number, take its middle digits, repeat. He knew exactly how disreputable the enterprise was. He said so in the line every textbook has quoted since — anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin. The sinning continued productively. Derrick Lehmer's linear congruential generator of 1949 powered decades of language runtimes. Its modern successors are faster, and their period — how far the sequence runs before it repeats — is enormously longer. What never changed is the theology. A generated sequence is not random, only unpredictable enough for the purpose — splendid for shuffles, samples and simulations, never for secrets. This machine keeps to the honest side of that line. Its seedless design leaves the state where it belongs, in the engine.
Randomness is how a program stops being predictable. A dice roll, a shuffled
deck, a coin flip, a wandering game character, a scattering of stars, a sampled
guess — all of them need a source of numbers that isn't the same every time.
random is that source, with the two shapes you almost always want:
a number somewhere in a range, or a whole number somewhere in a range. Because
it's seedless, there's nothing to set up and nothing to carry around. Reach
for it whenever you want a surprise and don't need to reproduce it exactly
later. (When you do need reproducibility, the trade-off is spelled out
below.)
Include the file and call the words — there's no state to manage. The one
thing worth understanding is what makes this machine unusual, so here it is
plainly: Random() is deliberately not a pure
function. Everywhere else, Shoddy makes a firm promise: call a
function twice with the same arguments and you get the same answer, every
time, no exceptions. That predictability is the property the whole language
is built to guarantee. Random is the one considered exception.
Call it twice with no arguments and it can, and should, give you two
different numbers. It's an effect, living at the edge of your
program in exactly the same family as Print — something that
reaches out to the world (here, the engine's running generator) rather than a
closed calculation. Treat it that way. Keep it near the edges of your code,
the way you'd keep printing there, and let the pure parts stay pure.
Include "random.shoddy"
Def Main()
Print(Random()) ' e.g. 0.417... — a fraction in [0, 1)
Print(RandomRange(1, 6)) ' e.g. 4.82... — a float in [1, 6)
Print(RandomInt(1, 6)) ' e.g. 5 — a die roll, 1 to 6
' Called twice, RandomInt gives two (probably) different answers —
' that impurity is the whole point.
Print(RandomInt(1, 100)) ' e.g. 73
Print(RandomInt(1, 100)) ' e.g. 12
Let deck = Shuffle(Range(1, 10)) ' e.g. [ 7 2 9 ... ] — all ten, reordered
Let hand = Sample(deck, 3) ' e.g. [ 4 9 1 ] — three, no repeats
Print(hand)
A few things worth remembering:
Rnd draws from the
engine's own auto-seeded generator. So there's no seed to pass in and no
state to thread through your program. That convenience is exactly what costs
you reproducibility — you can't rewind and get the same sequence again.RandomRange or RandomInt a hi that's
below lo, the program stops with an error. Low bound first, high
bound second.RandomInt includes both ends.
RandomInt(1, 6) can return any of 1, 2, 3, 4, 5, or 6 — a fair
six-sided die. RandomRange(lo, hi), being a float, can reach
lo but never quite touches hi.Seed builtin.The one word the runtime dispatches — not defined here, documented here
Rnd is not a Def. The engine dispatches it, and a
Def whose name is a builtin is refused. It is documented on this
page because random is the machine built directly on it. It
needs no Include — the same entry is in
machines/random.shoddy's own header block.
| Word | Description |
|---|---|
| Rnd() | A uniform random number in [0, 1) — zero possible, one
never. Impure, in the same way Print is: calling
it twice gives two different answers, and it is the single reason nothing in
this machine is a pure function. It draws from the engine's own auto-seeded
generator. That is what "seedless by construction" means here: there is no
generator state for a program to hold. |
Seed is not here, and its absence is the point.
Seed(n) reseeds this same generator, so it does govern every word
below. But this machine's whole design is that there is no seed to
create, so it is the wrong place to document the word that creates one.
Seed lives on math's page among the other
arithmetic primitives. Calling it there makes Random,
RandomRange, RandomInt, Shuffle and
Sample reproducible from that point on.
Every word, built on the Rnd builtin
| Word | Description |
|---|---|
| Random() | A random floating-point number in [0, 1)
— 0 possible, 1 never. The Rnd builtin, given a plain name. Not a
pure function: two calls can give two different answers. |
| RandomRange(lo, hi) | A random floating-point number in
[lo, hi). Stops the program with an error if hi is
below lo. |
| RandomInt(lo, hi) | A random whole number in [lo, hi],
both ends included — a fair die between the two bounds. Stops the program with
an error if hi is below lo. |
| Word | Description |
|---|---|
| Shuffle(xs) | A new list with the items of xs in
uniformly random order. The original is untouched, and every ordering is
equally likely. |
| Sample(xs, n) | A new list of n items drawn from
xs without replacement — no item is picked twice. Ask
for more than the list holds and you get all of it, shuffled. |
| DropAt(xs, k) | Helper the two above share: xs
without its k-th item. Pure, and occasionally handy on its
own. |
| User | How | |
|---|---|---|
| neural | Shuffle
deals the mini-batches; RandomRange scatters the initial
weights. |
None — a thin layer over the Rnd builtin, nothing else
required.