fn:random-number-generator

Returns a random number generator, which can be used to generate sequences of random numbers.

Signatures

fn:random-number-generator() as map(xs:string, item())
fn:random-number-generator($seed as xs:anyAtomicType?) as map(xs:string, item())

Properties

This function is deterministic, context-independent, focus-independent, and higher-order.

Rules

The function returns a random number generator. A random number generator is represented as a map containing three entries. The keys of each entry are strings:

  1. The entry with key "number" holds a random number; it is an xs:double greater than or equal to zero (0.0e0), and less than one (1.0e0).

  2. The entry with key "next" is a zero-arity function that can be called to return another random number generator.

    The properties of this function are as follows:

    • name: absent

    • parameter names: ()

    • signature: () => map(xs:string, item())

    • non-local variable bindings: none

    • implementation: implementation-dependent

  3. The entry with key "permute" is a function with arity 1 (one), which takes an arbitrary sequence as its argument, and returns a random permutation of that sequence.

    The properties of this function are as follows:

    • name: absent

    • parameter names: ("arg")

    • signature: (item()*) => item()*

    • non-local variable bindings: none

    • implementation: implementation-dependent

Calling the fn:random-number-generator function with no arguments is equivalent to calling the single-argument form of the function with an implementation-dependent seed.

Calling the fn:random-number-generator function with an empty sequence as the value of $seed is equivalent to calling the single-argument form of the function with an implementation-dependent seed.

If a $seed is supplied, it may be an atomic value of any type.

Both forms of the function are deterministic: calling the function twice with the same arguments, within a single execution scope, produces the same results.

The value of the number entry should be such that all eligible xs:double values are equally likely to be chosen.

The function returned in the permute entry should be such that all permutations of the supplied sequence are equally likely to be chosen.

The map returned by the fn:random-number-generator function may contain additional entries beyond those specified here, but it must match the type map(xs:string, item()). The meaning of any additional entries is implementation-defined. To avoid conflict with any future version of this specification, the keys of any such entries should start with an underscore character.

Notes

It is not meaningful to ask whether the functions returned in the next and permute functions resulting from two separate calls with the same seed are "the same function", but the functions must be equivalent in the sense that calling them produces the same sequence of random numbers.

The repeatability of the results of function calls in different execution scopes is outside the scope of this specification. It is recommended that when the same seed is provided explicitly, the same random number sequence should be delivered even in different execution scopes; while if no seed is provided, the processor should choose a seed that is likely to be different from one execution scope to another. (The same effect can be achieved explicitly by using fn:current-dateTime() as a seed.)

The specification does not place strong conformance requirements on the actual randomness of the result; this is left to the implementation. It is desirable, for example, when generating a sequence of random numbers that the sequence should not get into a repeating loop; but the specification does not attempt to dictate this.

Examples

The following example returns a random permutation of the integers in the range 1 to 100: fn:random-number-generator()?permute(1 to 100)

The following example returns a 10% sample of the items in an input sequence $seq, chosen at random: fn:random-number-generator()?permute($seq)[position() = 1 to (count($seq) idiv 10)]

The following code defines a function that can be called to produce a random sequence of xs:double values in the range zero to one, of specified length:

declare %public function r:random-sequence($length as xs:integer) as xs:double* {
  r:random-sequence($length, fn:random-number-generator())
};

declare %private function r:random-sequence($length as xs:integer, 
                                            $G as map(xs:string, item())) {
  if ($length eq 0)
  then ()
  else ($G?number, r:random-sequence($length - 1, $G?next()))
};

r:random-sequence(200);