Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
== Outdated egg! This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for [[/eggref/5/data-generators|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 [[https://wiki.call-cc.org/chicken-projects/egg-index-5.html|egg index]]. Otherwise, please consider porting this egg to the current version of CHICKEN. == data-generators [[toc:]] === Requirements [[/egg/random-bsd|random-bsd]], [[/egg/numbers|numbers]] === Repository [[https://bitbucket.org/certainty/data-generators/overview]] === Authors [[/users/david-krentzlin|David Krentzlin]] === 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 <enscript highlight=scheme> (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))) </enscript> ==== data-generators-literals <enscript highlight=scheme> (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]))) </enscript> === 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. <syntax>(generator ?body ...)</syntax> Creates a new generator. You can use this to define your own generators. Example: <enscript highlight=scheme> (define (my-gen start) (generator (+ start 42)) (<- (my-gen 10)) ;=> 52 </enscript> ==== Extracting data from generators <procedure>(<- gen)</procedure> Invokes the generator '''gen''' once and returns that value. <procedure>(<- amount gen)</procedure> Invokes the generator '''gen''' '''amount''' times and returns a list of values <procedure>(gen-for-each n proc gen)</procedure> 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. <procedure>(range lower upper)</procedure> 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. <procedure>(gen lower upper)</procedure> Creates a generator that can be created for the given argument types. Currently supported types are: * fixnum * flonum * char <procedure>(gen range)</procedure> 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 <procedure>(register-generator-for-type! type? gen)</procedure> 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 <parameter>gen-current-fixnum-min</parameter> The smallest fixnum that should be generated. <parameter>gen-current-fixnum-max</parameter> The biggest fixnum that should be generated ==== Primitives <procedure>(gen-constant value)</procedure> Generator that always returns '''value'''. <procedure>(fixnums ...)</procedure> Alias for '''gen-fixnum'''. <procedure>(gen-fixnum)</procedure> Generator for a fixnum between '''gen-current-fixnum-min''' and '''gen-current-fixnum-max'''. <procedure>(gen-fixnum range)</procedure> Generator for a fixnum within the given '''range''' <procedure>(gen-fixnum lower-bound upper-bound)</procedure> Generator for a fixnum between '''lower-bound''' and '''upper-bound''' <procedure>(odd-fixnums ...)</procedure> Alias for '''gen-odd-fixnum'''. <procedure>(gen-odd-fixnum ...)</procedure> This generator supports all the variations for '''gen-fixnum''' but it will only yield odd numbers <procedure>(even-fixnums ...)</procedure> Alias for '''gen-even-fixnum'''. <procedure>(gen-even-fixnum ...)</procedure> This generator supports all the variations for '''gen-fixnum''' but it will only yield even numbers <procedure>(gen-int8)</procedure> Generator for a fixnum between -127 and 127. <procedure>(gen-uint8)</procedure> Generator for a fixnum between 0 and 255. <procedure>(gen-int16)</procedure> Generator for a fixnum between -32767 and 3276. <procedure>(gen-uint16)</procedure> Generator for a fixnum between 0 and 65535. <procedure>(gen-int32)</procedure> Generator for a fixnum between -2147483647 and 2147483647. <procedure>(gen-uint32)</procedure> Generator for a fixnum between 0 and 4294967295. <procedure>(gen-int64)</procedure> Generator for a fixnum between -9223372036854775807 and 9223372036854775807. <procedure>(gen-uint64)</procedure> Generator for a fixnum between 0 and 18446744073709551615. <procedure>(gen-real)</procedure> Generator for a real number between 0.0 and 1.0. <procedure>(gen-real range)</procedure> Generator for a real number in the given '''range'''. <procedure>(gen-real lower-bound upper-bound)</procedure> Generator for a real number between '''lower-bound''' and '''upper-bound'''. <procedure>(gen-flonum)</procedure> Generator for a flonum between 0.0 and 1.0 or one of the special flonums +nan.0 +inf.0 and -inf.0. <procedure>(gen-flonum range)</procedure> Generator for a flonum in the given '''range'''. <procedure>(gen-flonum lower-bound upper-bound)</procedure> Generator for a flonum between '''lower-bound''' and '''upper-bound'''. <procedure>(gen-rational)</procedure> Generator for a rational number <procedure>(gen-rational nom-gen denom-gen)</procedure> Generator for a rational number where the nominator is generated with '''nom-gen''' and the denominator is generated with '''denom-gen'''. <procedure>(chars ...)</procedure> Alias for '''gen-char'''. <procedure>(gen-char)</procedure> Generator for a character from '''char-set:graphic'''. <procedure>(gen-char charset)</procedure> Generator for a character from the char-set '''charset'''. <procedure>(gen-char range)</procedure> Generator for a character in the given '''range'''. <procedure>(gen-char lower-bound upper-bound)</procedure> 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: <enscript highlight=scheme> (gen-char #\a #\z) </enscript> <procedure>(booleans)</procedure> Alias for '''gen-bool'''. <procedure>(gen-bool)</procedure> Generator for a random boolean value <procedure>(gen-procedure)</procedure> Generator for a procedure. This is equivalent to (gen-procedure (<- (gen-fixnum 0 max-arity)) (gen-bool)). <procedure>(gen-procedure arity return-gen)</procedure> 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'''. <procedure>(gen-sample candidates)</procedure> Generator that draws a random sample from the list of '''candidates'''. <procedure>(gen-series)</procedure> 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: <enscript highlight=scheme> ;; create lists with increasing size from 1 to 10 (<- 10 (gen-list-of (fixnums) (gen-series 1 10 add1))) </enscript> <procedure>(gen-series start end step)</procedure> 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 <parameter>(gen-current-default-size)</parameter> 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). <procedure>(gen-values-of . gens)</procedure> Generator that returns multiple values. Each value is generated with the given generators <procedure>(gen-pair-of car-gen cdr-gen)</procedure> Generator for a pair where the car is generated with '''car-gen''' and the cdr is generated with with '''cdr-gen'''. <procedure>(gen-sample-of . gens)</procedure> Generator that draws a random generator from the list of possible generators and invokes it once. <procedure>(gen-tuple-of . gens)</procedure> Generator for a tuple where each element is generated by the given generators. <procedure>(gen-string ...)</procedure> Alias for '''gen-string-of'''. <procedure>(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. <procedure>(gen-symbol ...)</procedure> Alias for '''gen-symbol-of''' <procedure>(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. <procedure>(gen-keyword ...)</procedure> Alias for '''gen-keyword-of''' <procedure>(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. <procedure>(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. <procedure>(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. <procedure>(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. <procedure>(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. <procedure>(gen-record ctor . slot-gens)</procedure> Generator for a record that is created with the given '''ctor''' where each slot is generated with the given '''slot-gens'''. <procedure>(gen-transform transformer gen)</procedure> Generator that retrieves values from '''gen''' and applies '''transformer''' to this value. <enscript highlight=scheme> ;; gen positive fixnums (gen-transform abs (fixnums)) </enscript> <syntax>(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)'''. <procedure>(gen-ipv4-address)</procedure> 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. <enscript highlight=scheme> (define (gen-foo) (generator "foo")) (with-size 3 (gen-list-of (gen-foo))) ;=> ("foo" "foo" "foo") </enscript> ==== Reader extensions Optionally you can use '''data-generators-literals''' to use reader-extensions that allow you to create ranges and generators. <syntax>#i[x .. y]</syntax> Creates a range from x to y inclusive. <syntax>#i[ .. y]</syntax> Creates a range from (gen-current-fixnum-min) to y inclusive. <syntax>#i[x .. ]</syntax> Creates a range from x to (gen-current-fixnum-max) inclusive. <syntax>#i[x ... y]</syntax> Creates a range from x to y exclusive. <syntax>#i[ ... y]</syntax> Creates a range from (gen-current-fixnum-min) to y exclusive. <syntax>#i[x ... ]</syntax> Creates a range from x to (gen-current-fixnum-max) exclusive. <syntax>#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: <enscript highlight=scheme> (use data-generators data-generators-literals) (<- #g[1 .. 10]) (<- #g[#\a ... #\z]) (<- #g[1.0 .. 10.3]) </enscript> === See also For a very exhaustive and systematic approach to all kinds of random sources see: [[/egg/srfi-27|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/>.
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you add 21 to 4?