SRFI 113 - Sets and bags

Sets and bags (also known as multisets) are unordered collections that can contain any Scheme object. Sets enforce the constraint that no two elements can be the same in the sense of the set’s associated equality predicate; bags do not.

Bags are like sets, but can contain the same object more than once. However, if two elements that are the same in the sense of the equality predicate, but not in the sense of eqv?, are both included, it is not guaranteed that they will remain distinct when retrieved from the bag. It is an error for a single procedure to be invoked on bags with different comparators.

The procedures for creating and manipulating bags are the same as those for sets, except that set is replaced by bag in their names, and that adjoining an element to a bag is effective even if the bag already contains the element. If two elements in a bag are the same in the sense of the bag’s comparator, the implementation may in fact store just one of them.

See the SRFI document for more information.

Constructors

set set-unfold bag bag-unfold

Predicates

set? set-contains? set-empty? set-disjoint? bag? bag-contains? bag-empty? bag-disjoint?

Accessors

set-member set-element-comparator bag-member bag-element-comparator

Updaters

set-adjoin set-adjoin! set-replace set-replace! set-delete set-delete! set-delete-all set-delete-all! set-search! bag-adjoin bag-adjoin! bag-replace bag-replace! bag-delete bag-delete! bag-delete-all bag-delete-all! bag-search!

The whole set

set-size set-find set-count set-any? set-every? bag-size bag-find bag-count bag-any? bag-every?

Mapping and folding

set-map set-for-each set-fold set-filter set-filter! set-remove set-remove! set-partition set-partition! bag-map bag-for-each bag-fold bag-filter bag-filter! bag-remove bag-remove! bag-partition bag-partition!

Copying and conversion

set-copy set->list list->set list->set! bag-copy bag->list list->bag list->bag!

Subsets

set=? set<? set>? set<=? set>=? bag=? bag<? bag>? bag<=? bag>=?

Set theory operations

set-union set-intersection set-difference set-xor set-union! set-intersection! set-difference! set-xor! bag-union bag-intersection bag-difference bag-xor bag-union! bag-intersection! bag-difference! bag-xor!

Additional bag procedures

bag-sum bag-sum! bag-product bag-product! bag-unique-size bag-element-count bag-for-each-unique bag-fold-unique bag-increment! bag-decrement! bag->set set->bag set->bag! bag->alist alist->bag

Comparators

set-comparator bag-comparator

set

(set comparator element ...)

Returns a newly allocated empty set. The comparator argument is a SRFI 114 comparator, which is used to control and distinguish the elements of the set. The elements are used to initialize the set.

set-unfold

(set-unfold comparator stop? mapper successor seed)

Create a newly allocated set as if by set using comparator. If the result of applying the predicate stop? to seed is true, return the set. Otherwise, apply the procedure mapper to seed. The value that mapper returns is added to the set. Then get a new seed by applying the procedure successor to seed, and repeat this algorithm.

bag

(bag comparator element ...)

Returns a newly allocated empty bag. The comparator argument is a SRFI 114 comparator, which is used to control and distinguish the elements of the bag. The elements are used to initialize the bag.

bag-unfold

(bag-unfold comparator stop? mapper successor seed)

Create a newly allocated bag as if by bag using comparator. If the result of applying the predicate stop? to seed is true, return the bag. Otherwise, apply the procedure mapper to seed. The value that mapper returns is added to the bag. Then get a new seed by applying the procedure successor to seed, and repeat this algorithm.

set?

(set? obj)

Returns #t if obj is a set, and #f otherwise.

set-contains?

(set-contains? set element)

Returns #t if element is a member of set and #f otherwise.

set-empty?

(set-empty? set)

Returns #t if set has no elements and #f otherwise.

set-disjoint?

(set-disjoint? set1 set2)

Returns #t if set1 and set2 have no elements in common and #f otherwise.

bag?

(bag? obj)

Returns #t if obj is a bag, and #f otherwise.

bag-contains?

(bag-contains? bag element)

Returns #t if element is a member of bag and #f otherwise.

bag-empty?

(bag-empty? bag)

Returns #t if bag has no elements and #f otherwise.

bag-disjoint?

(bag-disjoint? bag1 bag2)

Returns #t if bag1 and bag2 have no elements in common and #f otherwise.

set-member

(set-member set element default)

Returns the element of set that is equal, in the sense of set's equality predicate, to element. If element is not a member of set, default is returned.

set-element-comparator

(set-element-comparator set)

Returns the comparator used to compare the elements of set.

bag-member

(bag-member bag element default)

Returns the element of bag that is equal, in the sense of bag's equality predicate, to element. If element is not a member of bag, default is returned.

bag-element-comparator

(bag-element-comparator bag)

Returns the comparator used to compare the elements of bag.

#set-adjoin

(set-adjoin set element ...)

The set-adjoin procedure returns a newly allocated set that uses the same comparator as set and contains all the values of set, and in addition each element unless it is already equal (in the sense of the comparator) to one of the existing or newly added members. It is an error to add an element to set that does not return #t when passed to the type test procedure of the comparator.

set-adjoin!

(set-adjoin! set element ...)

The set-adjoin! procedure is the same as set-adjoin, except that it is permitted to mutate and return the set argument rather than allocating a new set.

set-replace

(set-replace set element)

The set-replace procedure returns a newly allocated set that uses the same comparator as set and contains all the values of set except as follows: If element is equal (in the sense of set’s comparator) to an existing member of set, then that member is omitted and replaced by element. If there is no such element in set, then set is returned unchanged.

set-replace!

(set-replace! set element)

The set-replace! procedure is the same asset-replace, except that it is permitted to mutate and return the set argument rather than allocating a new set.

set-delete

(set-delete set element ...)

The set-delete procedure returns a newly allocated set containing all the values of set except for any that are equal (in the sense of set’s comparator) to one or more of the elements. Any element that is not equal to some member of the set is ignored.

set-delete!

(set-delete! set element ...)

The set-delete! procedure is the same as set-delete, except that it is permitted to mutate and return the set argument rather than allocating a new set.

set-delete-all

(set-delete-all set element-list)

The set-delete-all and set-delete-all! procedures are the same as set-delete and set-delete!, except that they accept a single argument which is a list of elements to be deleted.

set-delete-all!

(set-delete-all! set element-list)

The set-delete-all and set-delete-all! procedures are the same as set-delete and set-delete!, except that they accept a single argument which is a list of elements to be deleted.

set-search!

(set-search! set element failure success)

The set is searched for element. If it is not found, then the failure procedure is tail-called with two continuation arguments, insert and ignore, and is expected to tail-call one of them. If element is found, then the success procedure is tail-called with the matching element of set and two continuations, update and remove, and is expected to tail-call one of them.

The effects of the continuations are as follows (where obj is any Scheme object):

In all cases, two values are returned: the possibly updated set and obj.

bag-adjoin

(bag-adjoin bag element ...)

The bag-adjoin procedure returns a newly allocated bag that uses the same comparator as bag and contains all the values of bag, and in addition each element unless it is already equal (in the sense of the comparator) to one of the existing or newly added members. It is an error to add an element to bag that does not return #t when passed to the type test procedure of the comparator.

bag-adjoin!

(bag-adjoin! bag element ...)

The bag-adjoin! procedure is the same as bag-adjoin, except that it is permitted to mutate and return the bag argument rather than allocating a new bag.

bag-replace

(bag-replace bag element)

The bag-replace procedure returns a newly allocated bag that uses the same comparator as bag and contains all the values of bag except as follows: If element is equal (in the sense of bag’s comparator) to an existing member of bag, then that member is omitted and replaced by element. If there is no such element in bag, then bag is returned unchanged.

bag-replace!

(bag-replace! bag element)

The bag-replace! procedure is the same as bag-replace, except that it is permitted to mutate and return the bag argument rather than allocating a new bag.

bag-delete

(bag-delete bag element ...)

The bag-delete procedure returns a newly allocated bag containing all the values of bag except for any that are equal (in the sense of bag’s comparator) to one or more of the elements. Any element that is not equal to some member of the bag is ignored.

bag-delete!

(bag-delete! bag element ...)

The bag-delete! procedure is the same as bag-delete, except that it is permitted to mutate and return the bag argument rather than allocating a new bag.

bag-delete-all

(bag-delete-all bag element-list)

The bag-delete-all and bag-delete-all! procedures are the same as bag-delete and bag-delete!, except that they accept a single argument which is a list of elements to be deleted.

bag-delete-all!

(bag-delete-all! bag element-list)

The bag-delete-all and bag-delete-all! procedures are the same as bag-delete and bag-delete!, except that they accept a single argument which is a list of elements to be deleted.

bag-search!

(bag-search! bag element failure success)

The bag is searched for element. If it is not found, then the failure procedure is tail-called with two continuation arguments, insert and ignore, and is expected to tail-call one of them. If element is found, then the success procedure is tail-called with the matching element of bag and two continuations, update and remove, and is expected to tail-call one of them.

The effects of the continuations are as follows (where obj is any Scheme object):

In all cases, two values are returned: the possibly updated bag and obj.

set-size

(set-size set)

Returns the number of elements in set as an exact integer.

set-find

(set-find predicate set failure)

Returns an arbitrarily chosen element of set that satisfies predicate, or the result of invoking failure with no arguments if there is none.

set-count

(set-count predicate set)

Returns the number of elements of set that satisfy predicate as an exact integer.

set-any?

(set-any? predicate set)

Returns #t if any element of set satisfies predicate, or #f otherwise. Note that this differs from the SRFI 1 analogue because it does not return an element of the set.

set-every?

(set-every? predicate set)

Returns #t if every element of set satisfies predicate, or #f otherwise. Note that this differs from the SRFI 1 analogue because it does not return an element of the set.

bag-size

(bag-size bag)

Returns the number of elements in bag as an exact integer.

bag-find

(bag-find predicate bag failure)

Returns an arbitrarily chosen element of bag that satisfies predicate, or the result of invoking failure with no arguments if there is none.

bag-count

(bag-count predicate bag)

Returns the number of elements of bag that satisfy predicate as an exact integer.

bag-any?

(bag-any? predicate bag)

Returns #t if any element of bag satisfies predicate, or #f otherwise. Note that this differs from the SRFI 1 analogue because it does not return an element of the bag.

bag-every?

(bag-every? predicate bag)

set-map

(set-map comparator proc set)

Applies proc to each element of set in arbitrary order and returns a newly allocated set, created as if by (set comparator), which contains the results of the applications. For example:

(set-map string-ci-comparator symbol->string (set eq? 'foo 'bar 'baz))
    => (set string-ci-comparator "foo" "bar" "baz")

Note that, when proc defines a mapping that is not 1:1, some of the mapped objects may be equivalent in the sense of comparator’s equality predicate, and in this case duplicate elements are omitted as in the set constructor. For example:

(set-map (lambda (x) (quotient x 2))
         integer-comparator
         (set integer-comparator 1 2 3 4 5))
    => (set integer-comparator 0 1 2)

If the elements are the same in the sense of eqv?, it is unpredictable which one will be preserved in the result.

set-for-each

(set-for-each proc set)

Applies proc to set in arbitrary order, discarding the returned values. Returns an unspecified result.

set-fold

(set-fold proc nil set)

Invokes proc on each member of set in arbitrary order, passing the result of the previous invocation as a second argument. For the first invocation, nil is used as the second argument. Returns the result of the last invocation, or nil if there was no invocation.

set-filter

(set-filter predicate set)

Returns a newly allocated set with the same comparator as set, containing just the elements of set that satisfy predicate.

set-filter!

(set-filter! predicate set)

A linear update procedure that returns a set containing just the elements of set that satisfy predicate.

set-remove

(set-remove predicate set)

Returns a newly allocated set with the same comparator as set, containing just the elements of set that do not satisfy predicate.

set-remove!

(set-remove! predicate set)

A linear update procedure that returns a set containing just the elements of set that do not satisfy predicate.

set-partition

(set-partition predicate set)

Returns two values: a newly allocated set with the same comparator as set that contains just the elements of set that satisfy predicate, and another newly allocated set, also with the same comparator, that contains just the elements of set that do not satisfy predicate.

set-partition!

(set-partition! predicate set)

A linear update procedure that returns two sets containing the elements of set that do and do not, respectively, not satisfy predicate.

bag-map

(bag-map comparator proc bag)

Applies proc to each element of bag in arbitrary order and returns a newly allocated bag, created as if by (bag comparator), which contains the results of the applications. For example:

(bag-map string-ci-comparator symbol->string (bag eq? 'foo 'bar 'baz))
    => (bag string-ci-comparator "foo" "bar" "baz")

Note that, when proc defines a mapping that is not 1:1, some of the mapped objects may be equivalent in the sense of comparator’s equality predicate, and in this case duplicate elements are omitted as in the bag constructor. For example:

(bag-map (lambda (x) (quotient x 2))
         integer-comparator
         (bag integer-comparator 1 2 3 4 5))
    => (bag integer-comparator 0 1 2)

If the elements are the same in the sense of eqv?, it is unpredictable which one will be preserved in the result.

bag-for-each

(bag-for-each proc bag)

Applies proc to bag in arbitrary order, discarding the returned values. Returns an unspecified result.

bag-fold

(bag-fold proc nil bag)

Invokes proc on each member of bag in arbitrary order, passing the result of the previous invocation as a second argument. For the first invocation, nil is used as the second argument. Returns the result of the last invocation, or nil if there was no invocation.

bag-filter

(bag-filter predicate bag)

Returns a newly allocated bag with the same comparator as bag, containing just the elements of bag that satisfy predicate.

bag-filter!

(bag-filter! predicate bag)

A linear update procedure that returns a bag containing just the elements of bag that satisfy predicate.

bag-remove

(bag-remove predicate bag)

Returns a newly allocated bag with the same comparator as bag, containing just the elements of bag that do not satisfy predicate.

bag-remove!

(bag-remove! predicate bag)

A linear update procedure that returns a bag containing just the elements of bag that do not satisfy predicate.

bag-partition

(bag-partition predicate bag)

Returns two values: a newly allocated bag with the same comparator as bag that contains just the elements of bag that satisfy predicate, and another newly allocated bag, also with the same comparator, that contains just the elements of bag that do not satisfy predicate.

bag-partition!

(bag-partition! predicate bag)

A linear update procedure that returns two bags containing the elements of bag that do and do not, respectively, not satisfy predicate.

set-copy

(set-copy set)

Returns a newly allocated set containing the elements of set, and using the same comparator.

set->list

(set->list set)

Returns a newly allocated list containing the members of set in unspecified order.

list->set

(list->set comparator list)

Returns a newly allocated set, created as if by set using comparator, that contains the elements of list. Duplicate elements (in the sense of the equality predicate) are omitted.

list->set!

(list->set! set list)

Returns a set that contains the elements of both set and list. Duplicate elements (in the sense of the equality predicate) are omitted.

bag-copy

(bag-copy bag)

Returns a newly allocated bag containing the elements of bag, and using the same comparator.

bag->list

(bag->list bag)

Returns a newly allocated list containing the members of bag in unspecified order.

list->bag

(list->bag comparator list)

Returns a newly allocated bag, created as if by bag using comparator, that contains the elements of list. Duplicate elements (in the sense of the equality predicate) are omitted.

list->bag!

(list->bag! bag list)

Returns a bag that contains the elements of both bag and list. Duplicate elements (in the sense of the equality predicate) are omitted.

set=?

(set=? set1 set2 ...)

Returns #t if each set contains the same elements.

Note: The following subset predicates do not obey the trichotomy law and therefore do not constitute a total order on sets.

set<?

(set<? set1 set2 ...)

Returns #t if each set other than the last is a proper subset of the following set, and #f otherwise.

set>?

(set>? set1 set2 ...)

Returns #t if each set other than the last is a proper superset of the following set, and #f otherwise.

set<=?

(set<=? set1 set2 ...)

Returns #t if each set other than the last is a subset of the following set, and #f otherwise.

set>=?

(set>=? set1 set2 ...)

Returns #t if each set other than the last is a superset of the following set, and #f otherwise.

bag=?

(bag=? bag1 bag2 ...)

Returns #t if each bag contains the same elements.

bag<?

(bag<? bag1 bag2 ...)

Returns #t if each bag other than the last is a proper subset of the following bag, and #f otherwise.

bag>?

(bag>? bag1 bag2 ...)

Returns #t if each bag other than the last is a proper superset of the following bag, and #f otherwise.

bag<=?

(bag<=? bag1 bag2 ...)

Returns #t if each bag other than the last is a subset of the following bag, and #f otherwise.

bag>=?

(bag>=? bag1 bag2 ...)

Returns #t if each bag other than the last is a superset of the following bag, and #f otherwise.

set-union

(set-union set1 set2 ...)

Return a newly allocated set that is the union of the sets.

set-intersection

(set-intersection set1 set2 ...)

Return a newly allocated set that is the intersection of the sets.

set-difference

(set-difference set1 set2 ...)

Return a newly allocated set that is the asymmetric difference of the sets.

Asymmetric difference is extended to more than two sets by taking the difference between the first set and the union of the others.

set-xor

(set-xor set1 set2)

Return a newly allocated set that is the symmetric difference of the sets.

Symmetric difference is not extended beyond two sets. Elements in the result set are drawn from the first set in which they appear.

set-union!

(set-union! set1 set2 ...)

Linear update procedures returning a set that is the union of the sets.

set-intersection!

(set-intersection! set1 set2 ...)

Linear update procedures returning a set that is the intersection of the sets.

set-difference!

(set-difference! set1 set2 ...)

Linear update procedures returning a set that is the asymmetric difference of the sets.

Asymmetric difference is extended to more than two sets by taking the difference between the first set and the union of the others.

set-xor!

(set-xor! set1 set2)

Linear update procedures returning a set that is the symmetric difference of the sets.

Symmetric difference is not extended beyond two sets. Elements in the result set are drawn from the first set in which they appear.

bag-union

(bag-union bag1 bag2 ...)

Return a newly allocated bag that is the union of the bags.

The number of equal elements in the result is the largest number of equal elements in any of the original bags.

bag-intersection

(bag-intersection bag1 bag2 ...)

Return a newly allocated bag that is the intersection of the bags.

The number of equal elements in the result is the smallest number of equal elements in any of the original bags.

bag-difference

(bag-difference bag1 bag2 ...)

Return a newly allocated bag that is the asymmetric difference of the bags.

Asymmetric difference is extended to more than two bags by taking the difference between the first bag and the union of the others.

The number of equal elements in the result is the number of equal elements in the first bag, minus the number of elements in the other bags (but not less than zero).

bag-xor

(bag-xor bag1 bag2)

Return a newly allocated bag that is the symmetric difference of the bags.

Symmetric difference is not extended beyond two bags. Elements in the result bag are drawn from the first bag in which they appear.

The number of equal elements in the result is the absolute value of the difference between the number of equal elements in the first and second bags.

bag-union!

(bag-union! bag1 bag2 ...)

Linear update procedures returning a bag that is the union of the bags.

The number of equal elements in the result is the largest number of equal elements in any of the original bags.

bag-intersection!

(bag-intersection! bag1 bag2 ...)

Linear update procedures returning a bag that is the intersection of the bags.

The number of equal elements in the result is the smallest number of equal elements in any of the original bags.

bag-difference!

(bag-difference! bag1 bag2 ...)

Linear update procedures returning a bag that is the asymmetric difference of the bags.

Asymmetric difference is extended to more than two bags by taking the difference between the first bag and the union of the others.

The number of equal elements in the result is the number of equal elements in the first bag, minus the number of elements in the other bags (but not less than zero).

bag-xor!

(bag-xor! bag1 bag2)

Linear update procedures returning a bag that is the symmetric difference of the bags.

Symmetric difference is not extended beyond two bags. Elements in the result bag are drawn from the first bag in which they appear.

The number of equal elements in the result is the absolute value of the difference between the number of equal elements in the first and second bags.

bag-sum

(bag-sum set1 set2 ... )

The bag-sum procedure returns a newly allocated bag containing all the unique elements in all the bags, such that the count of each unique element in the result is equal to the sum of the counts of that element in the arguments. It differs from bag-union by treating identical elements as potentially distinct rather than attempting to match them up.

bag-sum!

(bag-sum! bag1 bag2 ... )

The bag-sum! procedure is equivalent except that it is linear-update.

bag-product

(bag-product n bag)

The bag-product procedure returns a newly allocated bag containing all the unique elements in bag, where the count of each unique element in the bag is equal to the count of that element in bag multiplied by n.

bag-product!

(bag-product! n bag)

The bag-product! procedure is equivalent except that it is linear-update.

bag-unique-size

(bag-unique-size bag)

Returns the number of unique elements of bag.

bag-element-count

(bag-element-count bag element)

Returns an exact integer representing the number of times that element appears in bag.

bag-for-each-unique

(bag-for-each-unique proc bag)

Applies proc to each unique element of bag in arbitrary order, passing the element and the number of times it occurs in bag, and discarding the returned values. Returns an unspecified result.

bag-fold-unique

(bag-fold-unique proc nil bag)

Invokes proc on each unique element of bag in arbitrary order, passing the number of occurrences as a second argument and the result of the previous invocation as a third argument. For the first invocation, nil is used as the third argument. Returns the result of the last invocation.

bag-increment!

(bag-increment! bag element count)

Linear update procedure that returns a bag with the same elements as bag, but with the element count of element in bag increased by the exact integer count (but not less than zero).

bag-decrement!

(bag-decrement! bag element count)

Linear update procedure that returns a bag with the same elements as bag, but with the element count of element in bag decreased by the exact integer count (but not less than zero).

bag->set

(bag->set bag)

The bag->set procedure returns a newly allocated set containing the unique elements (in the sense of the equality predicate) of bag.

set->bag

(set->bag set)

The set->bag procedure returns a newly allocated bag containing the elements of set.

set->bag!

(set->bag! bag set)

The set->bag! procedure returns a bag containing the elements of both bag and set. In all cases, the comparator of the result is the same as the comparator of the argument or arguments.

bag->alist

(bag->alist bag)

The bag->alist procedure returns a newly allocated alist whose keys are the unique elements of bag and whose values are the number of occurrences of each element.

alist->bag

(alist->bag comparator alist)

The alist->bag returns a newly allocated bag based on comparator, where the keys of alist specify the elements and the corresponding values of alist specify how many times they occur.

set-comparator

These comparators are used to compare sets or bags, and allow sets of sets, bags of sets, etc.

Note that these comparators do not provide comparison procedures, as there is no ordering between sets or bags. It is an error to compare sets or bags with different element comparators.

bag-comparator

These comparators are used to compare sets or bags, and allow sets of sets, bags of sets, etc.

Note that these comparators do not provide comparison procedures, as there is no ordering between sets or bags. It is an error to compare sets or bags with different element comparators.