-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathsrfi-113-1.2.html
390 lines (221 loc) · 27.8 KB
/
srfi-113-1.2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
<!--
SPDX-FileCopyrightText: 2013 John Cowan <[email protected]>
SPDX-License-Identifier: MIT
-->
<!DOCTYPE HTML PUBLIC "" "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>SRFI 113: Sets, Bags, Integer Sets, Enumeration Sets</title>
</head>
<body>
<H1>Title</H1>
Sets, bags, integer sets, enumeration sets
<H1>Author</H1>
John Cowan
<p>
This SRFI is currently in ``draft'' status.
To see an explanation of
each status that a SRFI can hold, see <a
href="http://srfi.schemers.org/srfi-process.html">here</a>.
To provide input on this SRFI, please
<a href="mailto:srfi minus 113 at srfi dot schemers dot org">mail to
<code><srfi minus 113 at srfi dot schemers dot org></code></a>. See
<a href="../../srfi-list-subscribe.html">instructions here</a> to
subscribe to the list. You can access previous messages via
<a href="mail-archive/maillist.html">the archive of the mailing list</a>.
</p>
<ul>
<li>Received: <a href="http://srfi.schemers.org/srfi-113/srfi-113-1.1.html">2013/05/31</a></li>
<li>Draft: 2013/06/01-2013/08/01</li>
<li>Revised: <a href="http://srfi.schemers.org/srfi-113/srfi-113-1.2.html">2013/6/09</a></li>
</ul>
<H1>Abstract</H1><p><em>Sets</em> and <em>bags</em> (also known as multisets) are unordered mutable 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 <em>equivalence procedure</em>; bags do not. <em>Integer sets</em> are a variant of sets that can only contain non-negative exact integers that are less than a maximum value specified when the integer set is created, and that always treat numerical equality as their equivalence procedure. <em>Enumeration sets</em> are another variant that can only contain symbols chosen from a set of symbols represented by an <em>enumeration type</em>; the equivalence procedure for them is <em>eq?</em>.
</p><H1>Issues</H1><ol><li>R6RS provides <tt>define-enumeration</tt> to help set up enum-types. Is this worth having? Possible syntax is:
<blockquote><p><tt>(define-enumeration </tt><type-name><tt> (</tt><symbol> ...<tt>)</tt> <constructor><tt>)</tt>
</p><p>
This would bind <tt><type-name></tt> to the enum-type, and <tt>constructor</tt> to a curried version of <tt>make-enum-set</tt> that already knows what type to use.
</p></blockquote></li><li><p>Should there be a mechanism to convert between integer sets and integers as bitvectors, as defined in SRFI 33, SRFI 60, and R6RS?</p></li><li><p>(resolved)</p></li><li><p>How about <tt>set-intern!</tt>, which is like <tt>set-value</tt> but adds the element to the set if it's not already there?</p></li><li><p>Should there be a lexical syntax for sets? If so, how do we incorporate the equivalence procedure, which has no printed representation? Perhaps we only need to support the big five, or perhaps not even <code>eq?</code> as it is implementation-dependent.</p></li><li><p>(resolved)</p></li><li><p>(resolved)</p></li><li><p>Should we switch to unique enum objects rather than symbols?</p></li><li><p>(resolved)</p></li><li><p>Should set operations include an operation that adds an element to a set, returning a newly allocated set, but which does not require wrapping the new element in a set that is going to be thrown away immediately? In other words, should there be a functional analog to <code>set-add!</code>?</p></li>
<li><p>There are two constructors, <code>make-set</code> and <code>set</code> (and likewise
for the other types). This follows the general pattern of
<code>(make-){list,string,vector}</code> from R7RS-small. However, the <code>make-</code>
constructors construct an object of specified size with either undefined
contents or a repeated fill element; neither of these concepts makes any
sense for sets, and only minimal sense for bags.</p>
<p>So it would seem reasonable to only have <code>set</code> as the constructor.
Nevertheless, Schemers expect to find a <code>make-</code> constructor, and so I
have provided one that always constructs an empty set, though <code>set</code>
can do that just as well. Should we keep the status quo, eliminate
<code>make-set</code>, eliminate <code>set</code>, or cause it to be an alias for <code>set</code>?</p></li>
</ol>
<H1>Rationale</H1><p>Sets are a standard part of the libraries of many high-level programming languages, including Smalltalk, <a href="http://docs.oracle.com/javase/6/docs/api/java/util/Set.html">Java</a>, and <a href="http://www.cplusplus.com/reference/set/set/">C++</a>. <a href="http://docs.racket-lang.org/reference/sets.html">Racket</a> provides general sets similar to those of this proposal, though with fewer procedures, and there is a Chicken egg called <code>sets</code> (unfortunately undocumented), which provides a minimal set of procedures.</p><p>Bags are useful for counting anything from a fixed set of possibilities, e.g. the number of each type of error in a log file or the number of uses of each word in a lexicon drawn from a body of documents. Although other data structures can serve the same purpose, using bags clearly expresses the programmer's intent and can be optimized.</p><p>Although sets subsume both integer sets and enumeration sets, providing them separately allows for increased implementation efficiency. There are two Chicken eggs that provide integer sets: <a href="http://wiki.call-cc.org/eggref/4/iset#integer-sets"><code>iset</code></a>, which is conceptually similar to the integer sets described here, but using bignums rather than bytevectors; and <a href="http://wiki.call-cc.org/eggref/4/cis"><code>cis</code></a>, which uses lists of integer intervals.</p><p>The design of enumeration sets is founded on <a class="ext-link" href="http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-15.html">R6RS enumerations</a>, but with the addition of reified enumeration types along the lines suggested by <a class="ext-link" href="http://www.r6rs.org/formal-comments/comment-262.txt">R6RS Formal Comment #262</a>. The prefix <tt>enum</tt> is used in all cases instead of using both <tt>enum</tt> and <tt>enumeration</tt> as R6RS does. Approximate mappings are shown below.
</p><p>Insofar as possible, the names in this SRFI are harmonized with the names used for ordered collections (lists, strings, vectors, and bytevectors) in Scheme. However, <code>size</code> is used instead of <code>length</code> to express the number of elements in the collection, because <code>length</code> implies order.</p><H1>Specification</H1><p>The procedures in this SRFI are in the <code>(scheme sets)</code> and <code>(srfi xxx)</code> libraries (or <code>(srfi :xxx)</code> on R6RS). However, the sample implementation currently places them in the <code>(sets)</code> library instead.</p><p>
Sets, bags, integer sets, enumeration sets, and enumeration types are mutually disjoint, and disjoint from other types of Scheme objects.
</p><h2 id="Setprocedures">Set procedures</h2><p>
It is an error for a single procedure to be invoked on sets with different equivalence procedures.
</p><h3>Constructors</h3><p><tt>(make-set </tt><em>equivalence</em><tt>)</tt></p><p>
Returns a newly allocated empty set. <em>equivalence</em> is the equivalence procedure for the set. If it is coarser than <tt>equal</tt> (in the sense of R7RS-small 6.1), the implementation may signal an error; however, <tt>string-ci=?</tt> must be supported.
</p><p><tt>(set </tt><em>equivalence</em><tt> </tt><em>element</em><tt> ...)</tt></p><p>
Returns a newly allocated set with equivalence procedure <em>equivalence</em> and containing the <em>elements</em>.
</p><p><tt>(set-copy </tt><em>set</em><tt>)</tt></p><p>
Returns a newly allocated set containing the elements of <em>set</em>, with the same equivalence procedure.
</p><p><tt>(set-empty-copy </tt><em>set</em><tt>)</tt></p><p>
Returns a newly allocated set containing no elements with the same equivalence procedure as <em>set</em>.
</p><h3>Predicates</h3><p><tt>(set? </tt><em>obj</em><tt>)</tt></p><p>
Returns <tt>#t</tt> if <em>obj</em> is a set, and <tt>#f</tt> otherwise.
</p><p><tt>(set-member? </tt><em>set</em><tt> </tt><em>element</em><tt>)</tt></p><p>
Returns <tt>#t</tt> if <em>element</em> is a member of <em>set</em> and <tt>#f</tt> otherwise.
</p><h3>Mutators</h3><p><tt>(set-add! </tt><em>set</em><tt> </tt><em>element</em><tt>)</tt></p><p>
Adds <em>element</em> to <em>set</em> unless it is already a member. Returns an unspecified value.
</p><p><tt>(set-delete! </tt><em>set</em><tt> </tt><em>element</em><tt>)</tt></p><p>
Deletes <em>element</em> from <em>set</em> if it is a member. Returns <tt>#t</tt> if the element was a member, <tt>#f</tt> if not.
</p><h3>Mapping and folding</h3><p><tt>(set-map </tt><em>equivalence</em><tt> </tt><em>proc</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Applies <em>proc</em> to each element of <em>set</em> in arbitrary order and returns a newly allocated set with the equivalence predicate <em>equivalence</em> which contains the results of the applications. For example:
<blockquote>
(set-map string-ci=? symbol->string (set eq? 'foo 'bar 'baz))
=> (set string-ci=? "foo" "bar" "baz")
</blockquote>
</p><p><tt>(set-for-each </tt><em>proc</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Applies <em>proc</em> to <em>set</em> in arbitrary order, discarding the returned values. Returns unspecified results.
</p><p><tt>(set-fold </tt><em>proc</em><tt> </tt><em>nil</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Invokes <em>proc</em> on each member of <em>set</em> in arbitrary order, passing the result of the previous invocation as a second argument. For the first invocation, <em>nil</em> is used as the second argument. Returns the result of the last invocation.
</p><p><tt>(set-unfold </tt><em>equivalence continue? mapper successor seed</em><code>)</code></p><p><p>Create a new set as if by <code>make-set</code>. If the result of applying the predicate <em>continue?</em> to <em>seed</em> is <code>#f</code>, return the set. Otherwise, apply the procedure <em>mapper</em> to <code>seed</code>. The value that <em>mapper</em> returns is added to the set. Then get a new seed by applying the procedure <em>successor</em> to <em>seed</em>, and repeat this algorithm.</p><h3>Conversion</h3><tt>(set->list </tt><em>set</em><tt>)</tt></p><p>
Returns a newly allocated list containing the members of <em>set</em> in unspecified order. However, repeated calls to this procedure will return a list in the same order until the set is mutated.
</p><p><tt>(list->set </tt><em>equivalence list</em><tt>)</tt></p><p>
Returns a newly allocated set with equivalence predicate <em>equivalence</em> containing the elements of <em>list</em>.
</p><h3>Subsets</h3><p><tt>(set=? </tt><em>set</em> ...<tt>)</tt>
</p><p>
Returns <tt>#t</tt> if each <em>set</em> contains the same elements.
</p><p><tt>(set<? </tt><em>set</em> ...<tt>)</tt>
</p><p>
Returns <tt>#t</tt> if each <em>set</em> other than the last is a proper subset of the following <em>set</em>, and <tt>#f</tt> otherwise.
</p><p><tt>(set>? </tt><em>set</em> ...<tt>)</tt>
</p><p>
Returns <tt>#t</tt> if each <em>set</em> other than the last is a proper superset of the following <em>set</em>, and <tt>#f</tt> otherwise.
</p><p><tt>(set<=? </tt><em>set</em> ...<tt>)</tt>
</p><p>
Returns <tt>#t</tt> if each <em>set</em> other than the last is a subset of the following <em>set</em>, and <tt>#f</tt> otherwise.
</p><p><tt>(set>=? </tt><em>set</em> ...<tt>)</tt>
</p><p>
Returns <tt>#t</tt> if each <em>set</em> other than the last is a superset of the following <em>set</em>, and <tt>#f</tt> otherwise.
</p><h3>The whole set</h3><p><tt>(set-size </tt><em>set</em><tt>)</tt></p><p>
Returns the number of elements in <em>set</em>.
</p><p><tt>(set-filter </tt><em>predicate</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Returns a newly allocated set with the same equivalence predicate as <em>set</em> containing just the elements of <em>set</em> that satisfy <em>predicate</em>.
</p><p><tt>(set-remove </tt><em>predicate</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Returns a newly allocated set with the same equivalence predicate as <em>set</em> containing just the elements of <em>set</em> that do not satisfy <em>predicate</em>.
</p><p><tt>(set-partition </tt><em>predicate</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Returns two values, a newly allocated set with the same equivalence predicate as <em>set</em> containing just the elements of <em>set</em> that satisfy <em>predicate</em>, and another newly allocated set with the same equivalence predicate as <em>set</em> containing just the elements of <em>set</em> that do not satisfy <em>predicate</em>.
</p><p><tt>(set-count </tt><em>predicate</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Returns the number of elements of <em>set</em> that satisfy <em>predicate</em> as an exact integer.
</p><p><tt>(set-find </tt><em>predicate set failure</em><tt>)</tt></p><p>
Returns an arbitrarily chosen element of <em>set</em> that satisfies <em>predicate</em>, or the result of invoking <em>failure</em> with no arguments if there is none.
</p><p><tt>(set-any? </tt><em>predicate</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Returns <tt>#t</tt> if any element of <em>set</em> satisfies <em>predicate</em>, or <code>#f</code> otherwise. Note that this differs from the SRFI 1 analogue because it does not return a useful value.
</p><p><tt>(set-every? </tt><em>predicate</em><tt> </tt><em>set</em><tt>)</tt></p><p>
Returns <tt>#t</tt> if every element of <em>set</em> satisfies <em>predicate</em>, or <code>#f</code> otherwise. Note that this differs from the SRFI 1 analogue because it does not return a useful value.
</p><h3>Set operations</h3><p><tt>(set-union </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em> ...<tt>)</tt>
</p><p><tt>(set-intersection </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em> ...<tt>)</tt>
</p><p><tt>(set-difference </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em> ...<tt>)</tt>
</p><p><tt>(set-xor </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em><tt>)</tt></p><p>
Returns a newly allocated set that is the union, intersection, asymmetric difference, or symmetric difference of the <em>sets</em>. Asymmetric difference is extended to more than two sets by taking the difference between the first set and the union of the others. Symmetric difference is not extended beyond two sets. Elements in the result set are drawn from the first set in which they appear.
</p><p><tt>(set-union! </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em> ...<tt>)</tt>
</p><p><tt>(set-intersection! </tt><em>set<sub>1</sub></em><tt> </tt>set<sub>2</sub><em> ...<tt>)</tt>
</em></p><p><tt>(set-difference! </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em> ...<tt>)</tt>
</p><p><tt>(set-xor! </tt><em>set<sub>1</sub></em><tt> </tt><em>set<sub>2</sub></em><tt>)</tt></p><p>
The same as <tt>set-union</tt>, <tt>set-intersection</tt>, <tt>set-difference</tt>, and <tt>set-xor</tt> respectively, but may mutate the <em>set<sub>1</sub></em> argument.
</p><h3>Set value</h3><p><tt>(set-value </tt><em>set</em><tt> </tt><em>element</em><tt>)</tt></p><p>
Returns the element of <em>set</em> that is equal, in the sense of the equivalence predicate, to <em>element</em>. If <em>element</em> is not a member of the set, it is returned.
</p><h2 id="Bagprocedures">Bag procedures</h2><p>
Bags are like sets, but can contain the same object more than once. However, if two elements that are equal in the sense of the equivalence procedure, but not in the sense of <code>eqv?</code>, 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 equivalence procedures.
</p><p>
The procedures for creating and manipulating bags are the same as those for sets, except that <tt>set</tt> is replaced by <tt>bag</tt> in their names, and that adding an element to a bag is effective even if the bag already contains the element. There are no procedures <tt>bag-xor</tt>, <tt>bag-xor!</tt>, or <tt>bag-value</tt>.
</p><p><tt>(bag-element-count </tt><em>bag</em><tt> </tt><em>element</em><tt>)</tt></p><p>
Returns an exact integer representing the number of times that <em>element</em> appears in <em>bag</em>.
</p><p><tt>(bag-for-each-unique </tt><em>proc</em><tt> </tt><em>bag</em><tt>)</tt></p><p>
Applies <em>proc</em> to each unique element of <em>bag</em> in arbitrary order, passing the element and the number of times it occurs in <em>bag</em>, and discarding the returned values. Returns unspecified results.
</p><p><tt>(bag-fold-unique </tt><em>proc</em><tt> </tt><em>nil</em><tt> </tt><em>bag</em><tt>)</tt></p><p>
Invokes <em>proc</em> on each unique element of <em>bag</em> 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, <em>nil</em> is used as the third argument. Returns the result of the last invocation.
</p><p><tt>(bag-increment! </tt><em>bag<tt> </tt>element<tt> </tt>count</em><tt>)</tt></p><p><tt>(bag-decrement! </tt><em>bag<tt> </tt>element<tt> </tt>count</em><tt>)</tt></p><p>
Increases or decreases the element count of <em>element</em> in <em>bag</em> by the exact integer <em>count</em>.
</p><p><tt>(bag->set </tt><em>bag</em><tt>)</tt></p><p><tt>(set->bag </tt><em>set</em><tt>)</tt></p><p>
The <code>bag->set</code> procedure returns a newly allocated set containing the unique elements of <em>bag</em>. The <code>set->bag</code> procedure returns a newly allocated bag containing the elements of <em>set</em>.
</p><h2 id="Integersetprocedures">Integer set procedures</h2><p>
The elements of an integer set are non-negative exact integers less than the set's <em>limit</em>, which is specified when it is created. Except as noted below, the procedures for creating and manipulating integer sets are the same as those for sets, except that <tt>set</tt> is replaced by <tt>integer-set</tt> in their names, and references to equivalence predicates are replaced by limits, as the equivalence function is always <tt>=</tt>. Wherever a newly allocated integer set is returned, it has the same limit as the source sets. It is an error for a single procedure to be invoked on integer sets with different limits.
</p><p>
The procedure <tt>integer-set-value</tt> is just the identity function, so it is not provided.
</p><p><tt>(make-integer-set </tt><em>limit</em><tt>)</tt></p><p>
Returns a newly allocated integer set. The possible elements of the set are the exact integers from 0 to <em>limit</em> - 1, where <em>limit</em> is an exact non-negative integer. The set is empty.
</p><p><tt>(make-universal-integer-set </tt><em>limit</em><tt>)</tt></p><p>
Returns a newly allocated integer set. The possible elements of the set are the exact integers from 0 to <em>limit</em> - 1, where <em>limit</em> is an exact non-negative integer. The set contains all possible elements.
</p><p><tt>(integer-set-complement </tt><em>integer-set</em><tt>)</tt></p><p>
Returns a newly allocated integer set that is the complement of <em>integer-set</em>.
</p><p><tt>(integer-set-complement! </tt><em>integer-set</em><tt>)</tt></p><p>
Mutates <em>integer-set</em> to its complement.
</p><p><tt>(integer-set-min </tt><em>integer-set</em><tt>)</tt></p><p><tt>(integer-set-max </tt><em>integer-set</em><tt>)</tt></p><p>
Returns the smallest or largest integer in <i>integer-set</i>, or <tt>#f</tt> if there is none.
</p><p><tt>(integer-set-delete-min! </tt><em>integer-set</em><tt>)</tt></p><p><tt>(integer-set-delete-max! </tt><em>integer-set</em><tt>)</tt></p><p>
Returns and deletes the smallest or largest integer in <em>integer-set</em>, or <tt>#f</tt> if there is none.
</p><h2 id="Enumerationsets">Enumeration sets</h2><p>
Except as noted below, the procedures for creating and manipulating enumeration sets are the same as those for sets, except that <tt>set</tt> is replaced by <tt>enum-set</tt> in their names. Wherever a newly allocated enumeration set is returned, it has the same enumeration type as the source sets. It is an error for a single procedure to be invoked on enumeration sets with different enumeration types.
</p><p>
The procedure <tt>enum-set-value</tt> is just the identity function, so it is not provided.
</p><h3>Enum-type procedures</h3><p><tt>(make-enum-type </tt><em>enum-list</em><tt>)</tt></p><p>
Returns a newly allocated enumeration type suitable for constructing enumeration sets whose members are symbols. The elements of <em>enum-list</em> are either symbols or else pairs where the car is a symbol and the cdr is an exact integer called the <em>value</em> of the symbol. If the element is a symbol, the value is greater by 1 than the value of the previous symbol, or 0 if there was no previous symbol. Values are normally distinct, but <code>make-enum-type</code> intentionally does not enforce this, for compatibility with C/C++ external routines. The symbols are said to be <em>in the enumeration type</em>. In R6RS the function of this procedure is provided as part of <tt>make-enumeration</tt>, but the values (called indexes) are assigned from 0 on up.
</p><p><tt>(enum-type? </tt><em>obj</em><tt>)</tt></p><p>
Returns <tt>#t</tt> if <em>obj</em> is an enumeration type, and <tt>#f</tt> otherwise.
</p><p><tt>(enum-type->alist </tt><em>enum-type</em><tt>)</tt></p><p>
Return a newly allocated alist mapping the symbols in <em>enum-type</em> to their values.
</p><p><tt>(enum-type-symbol-value </tt><em>enum-type symbol</em><tt>)</tt></p><p>
Return the value of <em>symbol</em> in <em>enum-type</em>, or <tt>#f</tt> if it is not in <em>enum-type</em>. A loose R6RS analogue is the procedure returned by <tt>enum-type-indexer</tt> when applied to an enum-set belonging to <tt>enum-type</tt>.
</p><p><tt>(enum-type-symbol </tt><em>enum-type value</em><tt>)</tt></p><p>
Returns the first symbol whose value in <em>enum-type</em> is <em>value</em>, or <tt>#f</tt> if there is none.
</p><p><tt>(enum-value=? </tt><em>enum-type symbol</em> ...<tt>)</tt>
</p><p><tt>(enum-value<? </tt><em>enum-type symbol</em> ...<tt>)</tt>
</p><p><tt>(enum-value>? </tt><em>enum-type symbol</em> ...<tt>)</tt>
</p><p><tt>(enum-value<=? </tt><em>enum-type symbol</em> ...<tt>)</tt>
</p><p><tt>(enum-value>=? </tt><em>enum-type symbol</em> ...<tt>)</tt>
</p><p>
Returns <tt>#t</tt> if the values of the <em>symbols</em> are equal (which implies that the symbols themselves are <code>eq?</code>), monotonically increasing, monotonically decreasing, monotonically nondecreasing, and monoonically nonincreasing respectively, and <tt>#f</tt> otherwise.
</p><h3>Enum-set procedures</h3><p><tt>(make-enum-set </tt><em>enum-type</em><tt>)</tt></p><p>
Returns a newly allocated enumeration set. The possible elements of the set are the symbols in <em>enum-type</em>. The set is empty. The approximate R6RS equivalents are <tt>enum-set-constructor</tt> and <tt>make-enumeration</tt>.
</p><p><tt>(make-universal-enum-set </tt><em>enum-type</em><tt>)</tt></p><p>
Returns a newly allocated enumeration set. The possible elements of the set are the symbols in <em>enum-type</em>. The set contains all possible elements. The approximate R6RS equivalent is <tt>enum-set-universe</tt>.
</p><p><tt>(enum-set </tt><em>enum-type</em><tt> </tt><em>element</em> ...<tt>)</tt>
</p><p>
Returns a newly allocated enumeration set. The possible elements of the set are the symbols in <em>enum-type</em>. The set is initialized to contain the <em>elements</em>. There is no R6RS equivalent.
</p><p><tt>(list->enum-set </tt><em>enum-type</em><tt> </tt><em>list</em><tt>)</tt></p><p>
Returns a newly allocated enumeration set. The possible elements of the set are the symbols in <em>enum-type</em>. The set is initialized to contain the elements of <em>list</em>. There is no R6RS equivalent.
</p><p><tt>(enum-set-complement </tt><em>enum-set</em><tt>)</tt></p><p>
Returns a newly allocated enumeration set that is the complement of <em>enum-set</em>. This procedure is also in R6RS.
</p><p><tt>(enum-set-complement! </tt><em>enum-set</em><tt>)</tt></p><p>
Mutates <em>enum-set</em> to its complement. This procedure is also in R6RS.
</p><p><tt>(enum-set-min </tt><em>integer-set</em><tt>)</tt></p><p><tt>(enum-set-max </tt><em>integer-set</em><tt>)</tt></p><p>
Returns the smallest or largest symbol in symbol index order in <em>enum-set</em>, or <tt>#f</tt> if there is none.
</p><p><tt>(enum-set-delete-min! </tt><em>enum-set</em><tt>)</tt></p><p><tt>(enum-set-delete-max! </tt><em>enum-set</em><tt>)</tt></p><p>
Returns and deletes the smallest or largest symbol in symbol index order in <em>enum-set</em>, or <tt>#f</tt> if there is none.
</p><p><tt>(enum-set-projection </tt><em>enum-set</em><tt> </tt><em>enum-type</em><tt>)</tt></p><p>
Returns a newly allocated enumeration set of type <em>enum-type</em>. Its elements are the symbols belonging to <em>enum-set</em>, ignoring any symbols which are not in <em>enum-type</em>. This procedure is also in R6RS, but uses a second enum-set in place of <em>enum-type</em>.
</p><H1>Implementation</H1><p>Sets and bags are implemented as a thin veneer over hashtables, and integer sets over bytevectors. For clarity, the integer set implementation stores just one value into each bytevector element rather than the eight that would be possible. In turn, enumeration types are implemented over a hashtable from symbols to indexes, and enumeration sets over integer sets.</p><p>A sample implementation is <a href="sets.tar.gz">here</a>. The files <code>sets-impl.scm</code>, <code>bags-impl.scm</code>, <code>isets-impl.scm</code>, and <code>enums-impl.scm</code> are the basic code libraries for sets, bags, integer sets, and enumeration sets respectively. Each is divided into a section that makes use of the underlying collection and a section that doesn't. The file <code>count.scm</code> provides macros for conveniently looping over the bytevectors that underlie integer sets and enumeration sets. The file <code>srfi-4-shim.scm</code> is a minimal implementation of R7RS bytevectors on top of SRFI 4's u8vectors, just sufficient for this implementation, and may be useful for R5RS systems that do not provide R7RS bytevectors.</p><p>Two library definition files are provided: <code>sets.sld</code> provides an R7RS library named <code>(sets)</code> that exports the public procedures of this SRFI (the extension <code>.sld</code> is used by Chibi for library definition files). <code>sets.scm</code> is equivalent, but uses Chicken module syntax.</p><p>The file <code>sets-test.scm</code> is a test suite for this library. It uses Chicken's <code>test</code> egg, which is also provided on Chibi as an R7RS library named <code>(chibi test)</code>.</p>
<H1>Copyright</H1>
<p>Copyright (C) John Cowan 2013. All Rights Reserved.</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:</p>
<p>The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.</p>
<hr />
<address>Editor: <a href="mailto:srfi-editors at srfi dot schemers dot org">
Mike Sperber</a></address>
</body>
</html>