Erlang Central

List Generators

Revision as of 13:44, 22 March 2010 by TribbleFaith467 (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)



(This is a living page, please add your own list based generators here!)

Adam Lindberg Thomas Arts User:John Hughes

Non-Empty List

If you want to generate lists which can never be empty, it's fairly simple to wrap the standard list() generator in QuickCheck:

nelist(G) ->

This generator will generate one extra element and append it to the list to ensure that the list is never empty. But.. shrinking this list is sub-optimal, since it will not always discard the first element, even if a minimal counter example with only one element exists.

A better solution, which is in QuickCheck 1.19.2 and later, is

nelist(G) ->

This build-in non_empty is defined with a ?SUCHTHAT, which behaves much better in shrinking

non_empty(ListG) ->
     ?SUCHTHAT(List,ListG,List /= []).

In addition the non_empty generator also works for binaries.

List Without Duplicates

The easiest way to generate a list without duplicates, is to generate a list that may contain duplicates, and then remove them. For example, if a sorted list will do, then a list without duplicates can be generated by

ulist(G) -> 

Then you can generate a list of unique integers, for example, using


If you don't want all your lists to be sorted, then you could use the slightly more complex

ulist(G) ->

If you want to generate, for example, a list of pairs with different first components, then you should generate the list of first components first, and generate the list of pairs from it. For example,

     [{K,value()} || K <- Keys]).

Regexp POSIX Character Class Strings

String generators for all the POSIX character classes in regexp. Note: some of them do not generate printable strings in Erlang.

Also note that these generators are designed in such a way that the chosen list shrinks in length, but not in content. This avoids enormously large shrinking trees and gives rather quick shrinking results. However, it also may give rise to rather random looking output without knowing what actually is the cause of an error. In such cases, it is recommended to add a default value for shrinking.

alnum() -> default("0",list(oneof(seq($a, $z) ++ seq($A, $Z) ++ seq($0, $9)))).

If you happen to want shrinking in your content, use the choose generator.

-import(lists, [seq/2]).

%%% Alphanumeric characters ([a-zA-Z0-9]).
alnum() -> list(oneof(seq($a, $z) ++ seq($A, $Z) ++ seq($0, $9))).

%%% Alphabetic characters ([a-zA-Z]).
alpha() -> list(oneof(seq($a, $z) ++ seq($A, $Z))).

%%% ASCII characters ([\x00-\x7F]).
ascii() -> list(oneof(seq(0, 127))).

%%% Space and tab ([ \t]).
blank() -> list(oneof([$ , $\t])).

%%% Control characters ([\x00-\x1F\x7F]).
cntrl() -> list(oneof(seq(0, 31) ++ [127])).

%%% Digits ([0-9]).
digit() -> list(oneof(seq($0, $9))).

%%% Visible characters (i.e. anything except spaces, control
%%% characters, etc.) ([\x21-\x7E]).
graph() -> list(oneof(seq(33, 126))).

%%% Lowercase letters ([a-z]).
lower() -> list(oneof(seq($a, $z))).

%%% Visible characters and spaces (i.e. anything except control
%%% characters, etc.) ([\x20-\x7E]).
print() -> list(oneof(seq(32, 126))).

%%% Punctuation and symbols ([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]).
punct() -> list(oneof("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}\~")).

%%% All whitespace characters, including line breaks ([ \t\r\n\v\f]).
space() -> list(oneof([$ , $\t, $\r, $\n, $\v, $\f])).

%%% Uppercase letters ([A-Z]).
upper() -> list(oneof(seq($A, $Z))).

%%% Word characters (letters, numbers and underscores) ([A-Za-z0-9_]).
word() ->  list(oneof(seq($a, $z) ++ seq($A, $Z) ++ seq($0, $9) ++ "_")).

%%% Hexadecimal digits ([A-Fa-f0-9]).
xdigit() -> list(oneof(seq($A, $F) ++ seq($a, $f) ++ seq($0, $9))).