- Stage 0
- Authors: WhosyVox and Tab Atkins-Bittner
- Champions: Tab Atkins-Bittner
- Spec Text: currently this README
This proposal introduces several new functions for interacting with "collections" (iterables, Arrays, Maps, Sets, etc)
in a random manner.
This proposal stands alongside Simple Random Functions and Random Non-Uniform Distributions, and like those, uses the Random namespace object introduced by Seeded Random.
Shuffles an Array (or Array-like) in-place, using a fair shuffling method.
Returns a fresh Array containing the contents of coll,
shuffled using a fair shuffling method.
Returns an Array containing n randomly-selected entries from coll (which must be an iterable).
options are:
replace: Boolean: iffalse(the default), takes without replacement; every value in the returnedArraywill be from a unique index incoll. (Ifnis larger than the length ofcoll(modified bycounts), throw aRangeError.) Iftrue, takes with replacement; values in the returnedArraycan be repeats (and you can take any amount of them without error).counts: Iterable[Number]: provides the "multiplicity" of the entries in the matching index fromcoll.Random.take(["a", "b"], 2, {counts:[2, 3]})is identical toRandom.take(["a", "a", "b", "b", "b"], 2). (In particular, this example could return "a" or "b" multiple times, even tho it's not using replacement, just like the desugared example can.) If omitted, all counts are1. If the iterable is too short, missing entries are treated as0; if too long, excess entries are ignored. All numbers provided must be non-negative integers.weights: Iterable[Number]: provides the "weight" for the entries in the matching index fromcoll, allowing some entries to be more likely to be selected than others. If omitted, all entries have equal weight. If the iterable is too short, missing entries are treated as0; if too long, excess entries are ignored. All numbers provided must be non-negative numbers.countsandweightscan be used together; the specified weight for an entry is treated as applying to each of the multiple implied entries (not divided between them). That is,Random.take(["a", "b"], 2, {counts: [2, 3], weights:[1, 2]})is equivalent toRandom.take(["a", "a", "b", "b", "b"], 2, {weights: [1, 1, 2, 2, 2]}).
Identical in signature and function to Random.take,
except that it requires its coll argument (and its counts and weights options) to be Arrays or Array-likes.
Note
Issue #4 discusses the justification for this.
A random-access collection has significantly different optimal take() performance characteristics (a single random sample, and constant time and memory) than an iterable collection (either a single random sample but O(n) time and memory, or O(log(n)) random samples, O(1) memory, and O(n) time).
Returns a single randomly-selected entry from coll.
options are:
counts: Iterable[Number]: identical totake()'scountsoptionweights: Iterable[Number]: identical totake()'sweightsoption
(Random.sample(coll, options) is identical to Random.take(coll, 1, options)[0], just more straightforward and without constructing a throwaway Array.)
Identical in signature and function to Random.sample,
except that it requires its coll argument (and its counts and weights options) to be Arrays or Array-likes.
Returns a random entry from coll, and mutates coll to remove that entry.
Note
Issue #12
I should propose .pop() on Map and Set.
All of the above functions will also be defined on the Random.Seeded class as methods, with identical signatures and behavior. That is, Random.take(...) and new SeededRandom(...).take(...) will both work.
Precise generation algorithms will be defined for the Random.Seeded methods, to ensure reproducibility. It's recommended that the Random versions use the same algorithm, but not strictly required; doing so just lets you use an internal Random.Seeded object and avoid implementing the same function twice.
- 2025-06: Split out from Random Functions as part of the condition for that proposal advancing to Stage 1.