On this page:
2.1 Source of Randomness
current-random-source
random-source?
make-random-source
current-random-source-initialized?
assert-current-random-source-initialized!
get-current-random-source-byte-string
get-next-uint-from-current-random-source!
2.1.1 Example of Random Source Parameterization
2.2 Random Generation Functions
random
2.2.1 Common
random-bool
random-uint
random-int
random-seed-value
random-ref
random-in-bound-lists
2.2.2 Characters
random-char
random-char-in-range
random-char-in-bound-lists
random-ascii-char
random-ascii-lower-char
random-ascii-upper-char
random-ascii-alpha-char
random-ascii-numeral-char
random-ascii-alphanumeric-char
random-ascii-word-char
2.2.3 Strings
random-string-from-char-producing-proc
random-string
random-ascii-lower-string
random-ascii-upper-string
random-ascii-alpha-string
random-ascii-numeral-string
random-ascii-alphanumeric-string
random-ascii-word-string
2.2.4 Sentences
random-ascii-sentence
2.3 Macros
2.3.1 Using Racket’s Randomness Functions
wrap-external-randomness
require-clotho-wrapped
2.3.2 Randomness Abstraction
with-new-random-source
2.4 Version String
clotho-version-string
2.5 Stateful Execution
initialize-current-random-source!
uninitialize-current-random-source!
2.6 Avoiding Racket’s Built-In Functions
8.12

2 Clotho API🔗ℹ

Pierce Darragh <pierce.darragh@gmail.com>,
William Gallard Hatch <william@hatch.uno>,
and Eric Eide <eeide@cs.utah.edu>

 (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?

(current-random-source random-source)  void?
  random-source : random-source?
A parameter for defining the current source of deterministic randomness.

procedure

(random-source? v)  boolean?

  v : any/c
Checks whether a value is suitable for being used as the current-random-source.

procedure

(make-random-source v)  random-source?

  v : any/c
Creates a random-source?, which can be used to parameterize current-random-source. The v can be any of:

Checks whether the current-random-source has been initialized.

Raises an error if current-random-source-initialized? would return #f.

Returns an immutable byte string which records all randomness generations that have happened and all those which will happen (if they have not yet come to pass).

procedure

(get-next-uint-from-current-random-source!)

  (integer-in 0 (- (expt 2 32) 209))
Forces the current-random-source to produce an unsigned integer.

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)  exact-nonnegative-integer?

(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))
Identical to Racket’s racket/base:random function, but uses Clotho’s randomness source.

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?

Returns a random Boolean value.

procedure

(random-uint)  (integer-in 0 (- (expt 2 32) 209))

Returns a random unsigned integer.

procedure

(random-int)

  (integer-in (- (- (expt 2 31) 104)) (- (expt 2 31) 105))
Returns a random signed integer.

procedure

(random-seed-value)  (integer-in 0 (sub1 (expt 2 31)))

Returns a random unsigned integer value suitable for use as a seed (such as for make-random-source).

procedure

(random-ref seq)  any/c

  seq : sequence?
Returns a random element of the sequence.

procedure

(random-in-bound-lists bound-lists)  integer?

  bound-lists : (listof (list/c integer? integer?))
Takes a list containing boundary lists, where each boundary list is a list of a low and high number valid for use in random, where the boundary includes the low number and excludes the high number. The result is a random number drawn evenly from the various bounds.

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?

Returns a random Unicode character. The bytecode ranges used are 0-55295 and 57344-1114111.

procedure

(random-char-in-range seq)  char?

  seq : sequence?
(random-char-in-range low high)  char?
  low : integer?
  high : integer?
Returns a character corresponding to a randomly selected integer within the bounds or in the sequence given.

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?))
Like random-in-bound-lists, but converts the result into a character.

procedure

(random-ascii-char)  char?

Returns a random ASCII character, including control characters and null characters.

Returns a random ASCII lowercase character (bytecode 97-122; regex [a-z]).

Returns a random ASCII uppercase character (bytecode 65-90; regex [A-Z]).

Returns a random ASCII alphabetical character (bytecode 97-122 or 65-90; regex [a-zA-Z]). This range contains random-ascii-lower-char and random-ascii-upper-char.

Returns a random ASCII numerical character (bytecode 48-57; regex [0-9]).

Returns a random ASCII alphanumerical character (bytecode 97-122, 65-90, or 48-57; regex [a-zA-Z0-9]). This range contains both random-ascii-alpha-char and random-ascii-numeral-char.

procedure

(random-ascii-word-char)  char?

Returns a random ASCII word character (bytecode 97-122, 65-90, 48-57, or 95; regex [a-zA-Z0-9_]). This range contains random-ascii-alphanumeric-char as well as the underscore, #\_.

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
Returns a random string consisting of characters drawn from proc. The string will be of a random length no greater than bound. If the bound is #f, the maximum length of the string is 128.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-char.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-ascii-lower-char.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-ascii-upper-char.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-ascii-alpha-char.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-ascii-numeral-char.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-ascii-alphanumeric-char.

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
Returns a random string of characters with length no greater than bound. The characters are generated by calling random-ascii-word-char.

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
Returns a random string of words separated by spaces. Each word is produced by calling random-ascii-word-string, and the words are then joined.

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 ...+)
Installs a new current-pseudo-random-generator so that functions using the non-Clotho randomness functions will be handled with Clotho’s mechanisms. Most uses will not require the additional parameters.

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])

Must be used in a position where require is valid. Requires the phase-0 exports of module-name and automatically wraps them with wrap-external-randomness. Useful for wrapping libraries of random functions.

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 ...+)
Installs a new random-source? so that the current-random-source is not used for the body forms. Most uses will not require the additional parameters.

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.

A string containing the version info for Clotho.

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

(initialize-current-random-source! [val])  void?

  val : any/c = #f
Initialize the current-random-source with a new random-source?. The optional val must conform to the specifications of make-random-source.

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.