2 Clotho API
(require clotho) | package: clotho |
Clotho is a library that gives Racket support for parametric randomness. We define parametric randomness as a specific variety of random generation wherein the individual random choices can be externally manipulated by tuning “parameters.” A fuller definition is given below.
2.1 Source of Randomness
Clotho uses a specially designed random source to allow for easy manipulation of future random generations. This source, current-random-source, must be parameterized whenever a Clotho randomness function is called, or else an error will occur. To create a random source, the function make-random-source can be invoked during parameterization.
parameter
(current-random-source random-source) → void? random-source : random-source?
procedure
(random-source? v) → boolean?
v : any/c
procedure
v : any/c
#f – generates a random source free of any manipulation
bytes? – uses a byte sequence
(integer-in 0 (sub1 (expt 2 31))) – use v as a seed value
procedure
procedure
procedure
procedure
→ (integer-in 0 (- (expt 2 32) 209))
2.1.1 Example of Random Source Parameterization
A typical way to begin invoking Clotho’s randomness functions might look like:
(require clotho) ; Let's seed the source with the value 42. (parameterize ([current-random-source (make-random-source 42)]) (random)) ; => 0.5400850091450108
2.2 Random Generation Functions
These functions can be used within the context of the current-random-source to produce pseudo-random values. All of these functions are implemented in terms of random:
procedure
(random k) → exact-nonnegative-integer? k : (integer-in 1 4294967087) (random min max) → exact-nonnegative-integer? min : exact-integer?
max :
(integer-in (+ 1 min) (+ 4294967087 min))
2.2.1 Common
These are the most commonly used randomness functions. They provide facilities for generating Booleans, integers, and randomly selecting elements from a sequence.
procedure
(random-bool) → boolean?
procedure
(random-uint) → (integer-in 0 (- (expt 2 32) 209))
procedure
(random-seed-value) → (integer-in 0 (sub1 (expt 2 31)))
procedure
(random-ref seq) → any/c
seq : sequence?
procedure
(random-in-bound-lists bound-lists) → integer?
bound-lists : (listof (list/c integer? integer?))
In other words the following example with return with equal probability any number in the list (list 1 2 3 4 101 102):
(random-in-bound-lists (list (list 1 5) (list 101 103)))
2.2.2 Characters
In addition to the simple randomness functions, Clotho provides functions for randomly generating values from certain character classes.
procedure
(random-char) → char?
procedure
(random-char-in-range seq) → char?
seq : sequence? (random-char-in-range low high) → char? low : integer? high : integer?
When given bounds, as with the random function, the bounds include the low value and exclude the high value.
The easiest way to use this with a sequence is with the range function, as in:
(random-char-in-range (range 3 17))
procedure
(random-char-in-bound-lists bound-lists) → char?
bound-lists : (listof (list/c integer? integer?))
procedure
procedure
procedure
procedure
procedure
procedure
procedure
2.2.3 Strings
Convenience functions are also provided for generating random strings using the character generation functions of the previous section.
procedure
(random-string-from-char-producing-proc proc [ bound pre-proc post-proc]) → string? proc : (-> char?) bound : (or/c exact-nonnegative-integer? #f) = #f pre-proc : (or/c (-> char?) #f) = #f post-proc : (or/c (-> char?) #f) = #f
If the pre-proc character-producing function is given, the first character of the string will be produced with it. The remainder of the string will be no greater than (- bound 1) in length.
If the post-proc character-producing function is given, the last character of the string will be produced with it. The previous portion of the string will be no greater than (- bound 1) in length.
(If both pre-proc and post-proc are given, the interior portion of the string will be no greater than (- bound 2) in length.)
procedure
(random-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
procedure
(random-ascii-lower-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
procedure
(random-ascii-upper-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
procedure
(random-ascii-alpha-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
procedure
(random-ascii-numeral-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
procedure
(random-ascii-alphanumeric-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
procedure
(random-ascii-word-string [bound]) → string?
bound : (or/c exact-nonnegative-integer? #f) = #f
If the bound is #f, the maximum length of the string is 128.
2.2.4 Sentences
Clotho provides one function for generating random sentences as an example of how to use these convenience functions.
procedure
(random-ascii-sentence [ word-bound word-length-bound]) → string? word-bound : exact-nonnegative-integer? = 16 word-length-bound : exact-nonnegative-integer? = 8
The implementation of this function is:
(define (random-ascii-sentence [word-bound 16] [word-length-bound 8]) (string-join (for/list ([i (in-range (random 1 word-bound))]) (random-ascii-word-string (random 1 word-length-bound)))))
2.3 Macros
Clotho provides a few macros that make it easier to write code that relies on randomness functionality in certain circumstances.
2.3.1 Using Racket’s Randomness Functions
If you need to call a function which makes use of Racket’s built-in randomness functions but want for the values generated to be parameterized, Clotho provides a macro:
syntax
(wrap-external-randomness [#:prg prg:expr] [#:seed seed:expr] body ...+)
If given a #:prg argument, that prg will be installed as the new current-pseudo-random-generator. If instead given a #:seed argument, a completely clean pseudo-random-generator? will be created and installed as the current-pseudo-random-generator, and then seeded by calling (random-seed seed). Otherwise, a new pseudo-random-generator? is created and seeded with the next random-seed-value.
syntax
(require-clotho-wrapped module-name [#:provide? provide:bool])
If given #t for the #:provide? argument, the wrapped identifiers will also be provided.
(require clotho) (require-clotho-wrapped math/distributions) ; These functions from math/distributions now use ; Clotho's parametric randomness. (define d (normal-dist)) (define xs (sample d 100))
2.3.2 Randomness Abstraction
Sometimes, it may be beneficial to create regions of abstracted randomness. This can allow for controlling randomness with a less-fine grain. To support this, Clotho supplies a macro:
syntax
(with-new-random-source [#:random-source source:expr] [#:seed seed:expr] body ...+)
If given a #:random-source argument, that source will be installed as the new current-random-source. If instead given a #:seed argument, a new random-source? will be created by calling (make-random-source seed) and then installed as the current-random-source. Otherwise, a new random-source? is created using the next random-seed-value from the current-random-source.
2.4 Version String
Programs that want to re-run executions with the same randomness source probably want to be reproducible. But reproducibility usually doesn’t cross version boundaries. You might not only want to put your own program’s version information somewhere in the output, but also the version of Clotho.
value
2.5 Stateful Execution
(require clotho/stateful) | package: clotho |
By default, Clotho requires you to parameterize the current-random-source to use any of the included randomness functions. However, this can be a pain to deal with in some contexts, such as during a command-line REPL session.
Stateful (i.e., non-parameterized) randomness can be achieved by using the clotho/stateful module. This module automatically instantiates a current-random-source, and also allows for side-effecting manipulation of that random-source? without the need for any parameterize forms.
Two new functions are provided by clotho/stateful:
procedure
(uninitialize-current-random-source!) → void?
2.6 Avoiding Racket’s Built-In Functions
(require clotho/racket/base) | package: clotho |
Some people may like static guarantees that they are not accidentally calling Racket’s built-in randomness functions when they intended to use Clotho’s. To aid in this goal, Clotho provides clotho/racket/base.
This module provides everything defined in racket/base, except it leaves out the following procedures:
The clotho/racket/base module can also be used as a #lang for convenience. Note that require-ing the clotho/racket/base module inside a module written in #lang racket/base will not stop you from using those procedures, so using clotho/racket/base as a #lang is recommended.