Outdated egg!
This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for the CHICKEN 5 version of this egg, if it exists.
If it does not exist, there may be equivalent functionality provided by another egg; have a look at the egg index. Otherwise, please consider porting this egg to the current version of CHICKEN.
data-generators
TOC »
Requirements
Repository
https://bitbucket.org/certainty/data-generators/overview
Authors
Introduction
This egg provides primitives and combinators to generate random data. That may be useful for testing or other occasions where you just need a way to quickly generate data.
Examples
data-generators
(use json data-generators) ;; generate a json document (define (gen-json-doc #!optional (nesting 5)) (generator (with-output-to-string (lambda () (json-write (<- (gen-json-value nesting))))))) ;; this is the only tricky part ;; we need to stop the recursion at a certain level of nesting and yet ;; we want to reduce the construction of generators to a minimum (define (gen-json-value nesting) (let ((scalar (gen-json-scalar))) (if (positive? nesting) (gen-sample-of (gen-json-complex (sub1 nesting)) scalar) scalar))) (define (gen-json-scalar) (gen-sample-of (gen-json-null) (gen-json-string) (gen-json-number))) (define (gen-json-string) (with-size (range 0 20) (gen-string-of (gen-char #\A #\z)))) (define (gen-json-null) (gen-constant (void))) (define (gen-json-number) (gen-sample-of (gen-fixnum) (gen-real))) (define (gen-json-complex nesting) (gen-sample-of (gen-json-object (sub1 nesting)) (gen-json-array (sub1 nesting)))) (define (gen-json-object nesting) (gen-vector-of (gen-pair-of (gen-json-string) (gen-json-value (sub1 nesting))))) (define (gen-json-array nesting) (gen-list-of (gen-json-value (sub1 nesting)))) ;; now let's print our documents (with-size (range 0 20) (gen-for-each 10 print (gen-json-doc 10)))
data-generators-literals
(use data-generators data-generators-literals) ;; create a generator using the generator literal (print (<- #g[0 .. 100])) ;; create a generator using the range literal (print (<- (gen-list-of (gen-fixnum #i[0 ... 100])))
API
Generators
A generator is a means to create random values that possibly adhere to some constraints. By nature a generator represents an infinite stream of random values.
- (generator ?body ...)syntax
Creates a new generator. You can use this to define your own generators.
Example:
(define (my-gen start) (generator (+ start 42)) (<- (my-gen 10)) ;=> 52
Extracting data from generators
- <- genprocedure
Invokes the generator gen once and returns that value.
- <- amount genprocedure
Invokes the generator gen amount times and returns a list of values
- gen-for-each n proc genprocedure
Invokes the generator gen n times and applies proc to each value in turn. proc must be a procedure that takes two arguments. The first argument will be the value and the second argument will be the round in which the value was generated.
Ranges
Many generators accept a range argument that specifies the upper and lower bounds. You can use the following procedures to work with ranges.
- range lower upperprocedure
Creates a range that covers values from lower to upper. There are three variations of this:
- lower is #f and upper is not #f -> creates a range from (gen-current-fixnum-min) till upper
- lower is not #f and upper is #f -> creates a range from lower till (gen-current-fixnum-max)
- lower is not #f and upper is not #f -> creates a range from lower till upper
Generic generator
The library provides a generic generator procedure that is able to build the correct generator based on the type of the supplied arguments.
- gen lower upperprocedure
Creates a generator that can be created for the given argument types. Currently supported types are:
- fixnum
- flonum
- char
- gen rangeprocedure
Creates a generator that can be created for the given range. It dispatches on the type of the lower bound. Currently supported types are:
- fixnum
- flonum
- char
- register-generator-for-type! type? genprocedure
Registers a type-predicate with a generator. When the generic generator procedure gen is invoked, it will dispatch on the first argument using the registered type-predicates.
Parameters
- gen-current-fixnum-minparameter
The smallest fixnum that should be generated.
- gen-current-fixnum-maxparameter
The biggest fixnum that should be generated
Primitives
- gen-constant valueprocedure
Generator that always returns value.
- fixnums ...procedure
Alias for gen-fixnum.
- gen-fixnumprocedure
Generator for a fixnum between gen-current-fixnum-min and gen-current-fixnum-max.
- gen-fixnum rangeprocedure
Generator for a fixnum within the given range
- gen-fixnum lower-bound upper-boundprocedure
Generator for a fixnum between lower-bound and upper-bound
- odd-fixnums ...procedure
Alias for gen-odd-fixnum.
- gen-odd-fixnum ...procedure
This generator supports all the variations for gen-fixnum but it will only yield odd numbers
- even-fixnums ...procedure
Alias for gen-even-fixnum.
- gen-even-fixnum ...procedure
This generator supports all the variations for gen-fixnum but it will only yield even numbers
- gen-int8procedure
Generator for a fixnum between -127 and 127.
- gen-uint8procedure
Generator for a fixnum between 0 and 255.
- gen-int16procedure
Generator for a fixnum between -32767 and 3276.
- gen-uint16procedure
Generator for a fixnum between 0 and 65535.
- gen-int32procedure
Generator for a fixnum between -2147483647 and 2147483647.
- gen-uint32procedure
Generator for a fixnum between 0 and 4294967295.
- gen-int64procedure
Generator for a fixnum between -9223372036854775807 and 9223372036854775807.
- gen-uint64procedure
Generator for a fixnum between 0 and 18446744073709551615.
- gen-realprocedure
Generator for a real number between 0.0 and 1.0.
- gen-real rangeprocedure
Generator for a real number in the given range.
- gen-real lower-bound upper-boundprocedure
Generator for a real number between lower-bound and upper-bound.
- gen-flonumprocedure
Generator for a flonum between 0.0 and 1.0 or one of the special flonums +nan.0 +inf.0 and -inf.0.
- gen-flonum rangeprocedure
Generator for a flonum in the given range.
- gen-flonum lower-bound upper-boundprocedure
Generator for a flonum between lower-bound and upper-bound.
- gen-rationalprocedure
Generator for a rational number
- gen-rational nom-gen denom-genprocedure
Generator for a rational number where the nominator is generated with nom-gen and the denominator is generated with denom-gen.
- chars ...procedure
Alias for gen-char.
- gen-charprocedure
Generator for a character from char-set:graphic.
- gen-char charsetprocedure
Generator for a character from the char-set charset.
- gen-char rangeprocedure
Generator for a character in the given range.
- gen-char lower-bound upper-boundprocedure
Generator for a character from the char-set build from lower-bound to upper-bound. lower-bound must be <= upper-bound as compared with char<=?.
Example:
(gen-char #\a #\z)
- booleansprocedure
Alias for gen-bool.
- gen-boolprocedure
Generator for a random boolean value
- gen-procedureprocedure
Generator for a procedure. This is equivalent to (gen-procedure (<- (gen-fixnum 0 max-arity)) (gen-bool)).
- gen-procedure arity return-genprocedure
Generator that generates procedures with the given arity with 0 <= arity <= max-arity. max-arity is currently 20. The procedures that are generated return a value that is created by invoking return-gen.
- gen-sample candidatesprocedure
Generator that draws a random sample from the list of candidates.
- gen-seriesprocedure
Generator that returns values from the series starting at gen-current-fixnum-min till gen-current-fixnum-max by applying add1 in each step.
Example:
;; create lists with increasing size from 1 to 10 (<- 10 (gen-list-of (fixnums) (gen-series 1 10 add1)))
- gen-series start end stepprocedure
Generator that generates values from start to end with steps as specified by the one-argument-procedure step. The step procedure gets the current value during each application of the generator and must return the next possible value. The generator automatically wraps around and starts over if the end of the series has been reached.
Combinators
- gen-current-default-sizeparameter
A generator that must return a fixnum. It's used to determine the size for generators that can have a length. This defaults to (gen-uint8).
- gen-values-of #!rest gensprocedure
Generator that returns multiple values. Each value is generated with the given generators
- gen-pair-of car-gen cdr-genprocedure
Generator for a pair where the car is generated with car-gen and the cdr is generated with with cdr-gen.
- gen-sample-of #!rest gensprocedure
Generator that draws a random generator from the list of possible generators and invokes it once.
- gen-tuple-of #!rest gensprocedure
Generator for a tuple where each element is generated by the given generators.
- gen-string ...procedure
Alias for gen-string-of.
- (gen-string-of char-gen #!optional (size (gen-current-default-size)))procedure
Generator for a string where each character is generated from char-gen. The size parameter specifies the size of the strings that are generated. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- gen-symbol ...procedure
Alias for gen-symbol-of
- (gen-symbol-of #!optional (char-gen (gen-char char-set:letter+digit)) (size (gen-current-default-size)))procedure
Generator for a symbol where each character is generated from char-gen. The size parameter specifies the size of the strings that are generated. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- gen-keyword ...procedure
Alias for gen-keyword-of
- (gen-keyword-of #!optional (char-gen (gen-char char-set:letter+digit)) (size (gen-current-default-size)))procedure
Generator for a keyword where each character is generated from char-gen. The size parameter specifies the size of the strings that are generated. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- (gen-list-of gen #!optional (size (gen-current-default-size)))procedure
Generator for a list where each element is generated with the given generator gen. The size parameter specifies the size of the list that is generated. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- (gen-alist-of car-gen cdr-gen #!optional (size (gen-current-default-size)))procedure
Generator for an alist where each car is generated with car-gen and each cdr is generated with with cdr-gen. The size parameter specifies the size of the list that is generated. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- (gen-vector-of gen #!optional (size (gen-current-default-size)))procedure
Generator for a vector where each element is generated with the given generator gen. The size parameter specifies the size of the vector that is generated. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- (gen-hash-table-of key-gen value-gen #!optional (size (gen-current-default-size)) (equal? eq?))procedure
Generator for a hash-table where each key is generated by key-gen and each value is generated by value-gen. The size parameter specifies the size of the hash-table that is generated. The equal? parameter is passed directly to make-hash-table. It is expected to be a thunk that returns the size as a fixnum. See with-size for a more convenient way to adjust this.
- gen-record ctor #!rest slot-gensprocedure
Generator for a record that is created with the given ctor where each slot is generated with the given slot-gens.
- gen-transform transformer genprocedure
Generator that retrieves values from gen and applies transformer to this value.
;; gen positive fixnums (gen-transform abs (fixnums))
- (with-size size-spec ...)syntax
Use this to constrain the size of the data generated by the combinators. size-spec is either a fixnum a range or a generator. If it is a fixnum all data will be generated with the size equal to that fixnum. If it is a range, all data will be generated with a size that lies within that range. If it's a generator, this generator is expected to return the size.
Networking generators
In order to use these you need to (use data-generators-net).
- gen-ipv4-addressprocedure
Creates a generator that returns a string representing a dotted quad ipv4 address.
Defining your own generators
To define your own generators you can use the generator-syntax.
(define (gen-foo) (generator "foo")) (with-size 3 (gen-list-of (gen-foo))) ;=> ("foo" "foo" "foo")
Reader extensions
Optionally you can use data-generators-literals to use reader-extensions that allow you to create ranges and generators.
- #i[x .. y]syntax
Creates a range from x to y inclusive.
- #i[ .. y]syntax
Creates a range from (gen-current-fixnum-min) to y inclusive.
- #i[x .. ]syntax
Creates a range from x to (gen-current-fixnum-max) inclusive.
- #i[x ... y]syntax
Creates a range from x to y exclusive.
- #i[ ... y]syntax
Creates a range from (gen-current-fixnum-min) to y exclusive.
- #i[x ... ]syntax
Creates a range from x to (gen-current-fixnum-max) exclusive.
- #g[range-exp]syntax
Creates a generator by applying gen to the given range-expression. The range-expression is the same that the #i[]-reader-macro supports. It expands to (gen range-expression).
Example:
(use data-generators data-generators-literals) (<- #g[1 .. 10]) (<- #g[#\a ... #\z]) (<- #g[1.0 .. 10.3])
See also
For a very exhaustive and systematic approach to all kinds of random sources see: srfi-27
License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
A full copy of the GPL license can be found at <http://www.gnu.org/licenses/>.