summaryrefslogtreecommitdiffstats
path: root/srfi-225.html
diff options
context:
space:
mode:
authorGravatar John Cowan 2021-07-22 23:52:15 -0400
committerGravatar John Cowan 2021-07-22 23:52:15 -0400
commit8200d06659b703e747fe6f95124875259666a295 (patch)
treea3dbec78bdcc80e2b261daf3e3b0996d57516d50 /srfi-225.html
parenterrors (diff)
switching to explicit dtos
Diffstat (limited to '')
-rw-r--r--srfi-225.html190
1 files changed, 102 insertions, 88 deletions
diff --git a/srfi-225.html b/srfi-225.html
index 91a4004..7b797cc 100644
--- a/srfi-225.html
+++ b/srfi-225.html
@@ -43,97 +43,103 @@ similar to an existing hash table.</p>
<p>Until recently there was only one universally available mechanism for managing key-value pairs: alists. Most Schemes also support hash tables, but until R6RS there was no standard interface to them, and many implementations do not provide that interface.</p>
<p>Now, however, the number of such mechanisms is growing. In addition to both R6RS and R7RS hash tables, there are persistent ordered and hashed mappings from SRFI 146 and ordered key-value stores (often on a disk or a remote machine) from SRFI 167.</p>
-<p>It’s inconvenient for users if SRFIs or other libraries have to insist on accepting only a specific type of dictionary. This SRFI exposes a number of accessors, mutators, and other procedures that can be called on any dictionary, provided that its type has been registered with an implementation of this SRFI.</p>
-<p>This in turn requires that the dictionary type provides a predicate that can recognize it, plus at least these primitive operations: determine a dictionary’s current size; reference, update, or insert an element of the dictionary depending on its current contents; map over all the elements with a function mapping the old value to a new one; filter the elements based on their keys or values; and process all the elements using a side-effecting procedure.</p>
-<p>By using the procedures of this SRFI, a procedure can take a dictionary as an argument and make flexible use of it without knowing its exact type.</p>
+<p>It’s inconvenient for users if SRFIs or other libraries have to insist on accepting only a specific type of dictionary. This SRFI exposes a number of accessors, mutators, and other procedures that can be called on any dictionary, provided that a <em>dictionary type object</em> (DTO) is available for it: either exported from this SRFI, or from other SRFIs or libraries, or created by the user.</p>
+<p>This in turn requires that the DTO provides a predicate that can recognize its dictionaries, plus at least these primitive operations: determine a dictionary’s current size; reference, update, or insert an element of the dictionary depending on its current contents; map over all the elements with a function mapping each old value to a new one; filter the elements based on their keys or values; and process all the elements using a procedure invoked for its side effects.</p>
+<p>By using the procedures of this SRFI, a procedure can take a DTO and a dictionary as an argument and make flexible use of the dictionary without knowing its exact type.</p>
<p>Note that dictionaries must still be constructed using type-specific constructors, as the required and optional arguments differ in each case.</p>
<h2 id="specification">Specification</h2>
-<p>In order for the system to know that an object is a dictionary, a predicate must be defined that recognizes that type of dictionary. Then the predicate must be registered along with procedures that know how to manipulate the dictionary. At least the six basic dictionary procedures (see below) must be registered, but more may be provided at registration time.</p>
<p>We call a specific key-value pair an <em>association</em>. This is why an alist, or association list, is called that; it is a list of associations represented as pairs.</p>
-<p>When a key argument is said to be the same as some key of the dictionary, it means that they are the same in the sense of the dictionary’s equality predicate. It is assumed that no dictionary contains two keys that are the same in this sense.</p>
+<p>When a key argument is said to be the same as some key of the dictionary, it means that they are the same in the sense of the dictionary’s implicit or explicit equality predicate. It is assumed that no dictionary contains two keys that are the same in this sense.</p>
<h3 id="lists-as-dictionaries">Lists as dictionaries</h3>
-<p>The exact set of pre-registered dictionaries depends on their availability in a given implementation. However, lists are supported as dictionaries using the specification in this section. If two keys are the same (in the sense of the specified equality predicate), then all but the first are treated as if they did not exist.</p>
-<p>If the car of a list is a symbol, then the list is assumed to be a property list, alternating symbol keys with values. Mutation operations actually mutate the property list whenever possible. The equality predicate of this type of dictionary is <code>eq?</code>.</p>
-<p>If a list is empty, or its car is a pair, then the list is assumed to be an alist. New values are added to the beginning of an alist and the new alist is returned; deletion does not mutate the alist, but returns an alist that may or may not share storage with the original alist. If an association has been updated, then both the new and the old association may be processed by the whole-dictionary procedures. The equality predicate of this type of dictionary is <code>equal?</code>. The examples in this SRFI use alists.</p>
-<p>In all other cases, lists are not treated as dictionaries unless an appropriate dictionary type has been registered.</p>
-In the following examples, <code>dict</code> has the value of
+<p>Lists are supported as dictionaries using the specification in this section. If two keys are the same (in the sense of the specified equality predicate), then all but the first are treated as if they did not exist.</p>
+<p>If <code>plist-dto</code> (see below) is used with a list, then the list is assumed to be a property list, alternating symbol keys with values. Mutation operations actually mutate the property list whenever possible. The equality predicate of this type of dictionary is <code>eq?</code>.</p>
+<p>If a list is empty, or its car is a pair, then the list can be treated as an alist. New values are added to the beginning of an alist and the new alist is returned; deletion does not mutate the alist, but returns an alist that may or may not share storage with the original alist. If an association has been updated, then both the new and the old association may be processed by the whole-dictionary procedures. The examples in this SRFI use alists.</p>
+<p>However, an alist (unlike a hashtable or mapping) does not know with which equality predicate its users intend to use to search it. Therefore, rather than exporting a single DTO for alists, this SRFI provides a procedure <code>make-alist-dto</code> takes an equality predicate and returns a DTO specialized for manipulation of alists using that predicate.</p>
+<p>In all other cases, lists cannot be treated as dictionaries unless a DTO exists.</p>
+<h3>Procedures</h3>
+<p>In the following examples, <code>dict</code> has the value of
<code>(list '(1 . 2) '(3 . 4) '(5 . 6))</code> at the beginning of the example.
Consequently, previous examples don't affect later ones.
+In addition, <code>aed</code> is defined as <code>alist-eqv-dto</code>
+in order to save horizontal space and improve readability.
+<p>The <em>dto</em> argument is not discussed below, but it is an error
+if invoking the <code>dictionary?</code> procedure used to make the DTO
+on <em>dictionary</em> returns <code>#f</code>.</p>
<h3 id="predicates">Predicates</h3>
-<p><code>(dictionary?</code>&nbsp;<em>obj</em><code>)</code></p>
+<p><code>(dictionary?</code>&nbsp;<em>dto obj</em><code>)</code></p>
<p>Returns <code>#t</code> if <em>obj</em> answers <code>#t</code> to some registered predicate, and <code>#f</code> otherwise.</p>
-<blockquote><pre>(define dict (list '(1 . 2) '(3 . 4) '(5 . 6)))
-(dictionary? dict) =&gt; #t</pre></blockquote>
-<p><code>(dict-empty?</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<blockquote><pre>(define aed dict (list '(1 . 2) '(3 . 4) '(5 . 6)))
+(dictionary? aed dict) =&gt; #t</pre></blockquote>
+<p><code>(dict-empty?</code>&nbsp;<code>)</code></p>
<p>Returns <code>#t</code> if <em>dictionary</em> contains no associations and <code>#f</code> if it does contain associations.</p>
<blockquote><pre>(dict-empty? &#39;()) =&gt; #t
-(dict-empty? dict) =&gt; #f</pre></blockquote>
-<p><code>(dict-contains?</code>&nbsp;<em>dictionary key</em><code>)</code></p>
-<blockquote><pre>(dict-contains? dict 1) =&gt; #t
-(dict-contains? dict 2) =&gt; #f</pre></blockquote>
+(dict-empty? aed dict) =&gt; #f</pre></blockquote>
+<p><code>(dict-contains?</code>&nbsp;<em>dto dictionary key</em><code>)</code></p>
+<blockquote><pre>(dict-contains? aed dict 1) =&gt; #t
+(dict-contains? aed dict 2) =&gt; #f</pre></blockquote>
<p>Returns <code>#t</code> if one of the keys of <em>dictionary</em> is the same as <em>key</em>, and <code>#f</code> otherwise.</p>
<h3 id="lookup">Lookup</h3>
-<p><code>(dict-ref</code>&nbsp;<em>dictionary key</em> [<em>failure</em> [<em>success</em>] ]<code>)</code></p>
+<p><code>(dict-ref</code>&nbsp;<em>dto dictionary key</em> [<em>failure</em> [<em>success</em>] ]<code>)</code></p>
<p>If <em>key</em> is the same as some key of <em>dictionary</em>, then invokes <em>success</em> on the corresponding value and returns its result. If <em>key</em> is not a key of <em>dictionary</em>, then invokes the thunk <em>failure</em> and returns its result. The default value of <em>failure</em> signals an error; the default value of <em>success</em> is the identity procedure.</p>
-<blockquote><pre>(dict-ref dict 1 (lambda () &#39;()) list) =&gt; (1) ; Success wraps value in a list
-(dict-ref dict 2 (lambda () &#39;()) list) =&gt; () ; Failure returns empty list</pre></blockquote>
-<p><code>(dict-ref/default</code>&nbsp;<em>dictionary key default</em><code>)</code></p>
+<blockquote><pre>(dict-ref aed dict 1 (lambda () &#39;()) list) =&gt; (1) ; Success wraps value in a list
+(dict-ref aed dict 2 (lambda () &#39;()) list) =&gt; () ; Failure returns empty list</pre></blockquote>
+<p><code>(dict-ref/default</code>&nbsp;<em>dto dictionary key default</em><code>)</code></p>
<p>If <em>key</em> is the same as some key of <em>dictionary</em> then returns the corresponding value. If not, then returns <em>default</em>.</p>
-<blockquote><pre>(dict-ref/default dict 1 #f) =&gt; 1
-(dict-ref/default dict 1 #f) =&gt; #f</pre></blockquote>
+<blockquote><pre>(dict-ref/default aed dict 1 #f) =&gt; 1
+(dict-ref/default aed dict 1 #f) =&gt; #f</pre></blockquote>
<h3 id="mutation">Mutation</h3>
<p>All these procedures are linear-update: they may return either a new dictionary object (which may or may not share storage with the <em>dictionary</em> argument), or the same dictionary object, mutated. In either case, it is an error to access the dictionary later through any other reference to it, as that reference may have been invalidated.</p>
-<p><code>(dict-set!</code>&nbsp;<em>dictionary obj</em> …<code>)</code></p>
+<p><code>(dict-set!</code>&nbsp;<em>dto dictionary obj</em> …<code>)</code></p>
<p>Returns a dictionary that contains all the associations of <em>dictionary</em> plus those specified by <em>objs</em>, which alternate between keys and values. If a key to be added already exists in <em>dictionary</em>, the new value prevails.</p>
<blockquote><pre>; new values are prepended
-(dict-set! dict 7 8) =&gt; ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
-(dict-set! dict 3 5) =&gt; ((3 . 5) (1 . 2) (3 . 4) (5 . 6)</pre></blockquote>
-<p><code>(dict-adjoin!</code>&nbsp;<em>dictionary objs</em><code>)</code></p>
+(dict-set! aed dict 7 8) =&gt; ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
+(dict-set! aed dict 3 5) =&gt; ((3 . 5) (1 . 2) (3 . 4) (5 . 6)</pre></blockquote>
+<p><code>(dict-adjoin!</code>&nbsp;<em>dto dictionary objs</em><code>)</code></p>
<p>Returns a dictionary that contains all the associations of <em>dictionary</em> plus those specified by <em>objs</em>, which alternate between keys and values. If a key to be added already exists in <em>dictionary</em>, the old value prevails.</p>
<blockquote><pre>; new values are prepended to alists
-(dict-adjoin! dict 7 8) =&gt; ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
-(dict-adjoin! dict 3 5) =&gt; ((1 . 2) (3 . 4) (5 . 6)</pre></blockquote>
-<p><code>(dict-delete!</code>&nbsp;<em>dictionary key</em> …<code>)</code></p>
+(dict-adjoin! aed dict 7 8) =&gt; ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
+(dict-adjoin! aed dict 3 5) =&gt; ((1 . 2) (3 . 4) (5 . 6)</pre></blockquote>
+<p><code>(dict-delete!</code>&nbsp;<em>dto dictionary key</em> …<code>)</code></p>
<p>Returns a dictionary that contains all the associations of <em>dictionary</em> except those whose keys are the same as one of the <em>keys</em>.</p>
<blockquote><pre>; new values are prepended
-(dict-delete! dict 1 3) =&gt; ((5. 6)) ; may share
-(dict-delete! dict 5) =&gt; ((1 . 2) (3 . 4)</pre></blockquote>
-<p><code>(dict-delete-all!</code>&nbsp;<em>dictionary keylist</em><code>)</code></p>
+(dict-delete! aed dict 1 3) =&gt; ((5. 6)) ; may share
+(dict-delete! aed dict 5) =&gt; ((1 . 2) (3 . 4)</pre></blockquote>
+<p><code>(dict-delete-all!</code>&nbsp;<em>dto dictionary keylist</em><code>)</code></p>
<p>Returns a dictionary with all the associations of <em>dictionary</em> except those whose keys are the same as some member of <em>keylist</em>.</p>
-<blockquote><pre>(dict-delete-all! dict &#39;(1 3)) =&gt; ((5 . 6))</pre></blockquote>
-<p><code>(dict-replace!</code>&nbsp;<em>dictionary key value</em><code>)</code></p>
+<blockquote><pre>(dict-delete-all! aed dict &#39;(1 3)) =&gt; ((5 . 6))</pre></blockquote>
+<p><code>(dict-replace!</code>&nbsp;<em>dto dictionary key value</em><code>)</code></p>
<p>Returns a dictionary that contains all the associations of <em>dictionary</em> except as follows: If <em>key</em> is the same as a key of <em>dictionary</em>, then the association for that key is omitted and replaced by the association defined by the pair <em>key</em> and <em>value</em>. If there is no such key in <em>dictionary</em>, then dictionary is returned unchanged.</p>
-<blockquote><pre>(dict-replace! dict 1 3) =&gt; ((1 . 3) (1 . 2) (3 . 4) (5 . 6)) </pre></blockquote>
-<p><code>(dict-intern!</code>&nbsp;<em>dictionary key failure</em>)</p>
+<blockquote><pre>(dict-replace! aed dict 1 3) =&gt; ((1 . 3) (1 . 2) (3 . 4) (5 . 6)) </pre></blockquote>
+<p><code>(dict-intern!</code>&nbsp;<em>dto dictionary key failure</em>)</p>
<p>If there is a key in <em>dictionary</em> that is the same as <em>key</em>, returns two values, <em>dictionary</em> and the value associated with <em>key</em>.
Otherwise, returns two values, a dictionary that contains all the associations of <em>dictionary</em> and in addition a new association that maps <em>key</em> to the result of invoking <em>failure</em>, and the result of invoking <em>failure</em>.</p>
-<blockquote><pre>(dict-intern! dict 1 (lambda () #f)) =&gt; ; 2 values
+<blockquote><pre>(dict-intern! aed dict 1 (lambda () #f)) =&gt; ; 2 values
((1 . 2) (3 . 4) (5 . 6))
3
-(dict-intern! dict 2 (lambda () #f)) =&gt; ; 2 values
+(dict-intern! aed dict 2 (lambda () #f)) =&gt; ; 2 values
((2 . #f) (1 . 2) (3 . 4) (5 . 6))
#f</pre></blockquote>
-<p><code>(dict-update!</code>&nbsp;<em>dictionary key updater</em> [<em>failure</em> [<em>success</em>] ]<code>)</code></p>
+<p><code>(dict-update!</code>&nbsp;<em>dto dictionary key updater</em> [<em>failure</em> [<em>success</em>] ]<code>)</code></p>
<p>Retrieves the value of <em>key</em> as if by <code>dict-ref</code>, invokes <em>updater</em> on it, and sets the value of <em>key</em> to be the result of calling <em>updater</em> as if by <code>dict-set</code>, but may do so more efficiently. Returns the updated dictionary. The default value of <em>failure</em> signals an error; the default value of <em>success</em> is the identity procedure.</p>
-<p><code>(dict-update/default!</code>&nbsp;<em>dictionary key updater default</em><code>)</code></p>
+<p><code>(dict-update/default!</code>&nbsp;<em>dto dictionary key updater default</em><code>)</code></p>
<p>Retrieves the value of <em>key</em> as if by <code>dict-ref/default</code>, invokes <em>updater</em> on it, and sets the value of <em>key</em> to be the result of calling <em>updater</em> as if by <code>dict-set</code>, but may do so more efficiently. Returns the updated dictionary.</p>
-<p><code>(dict-pop!</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<p><code>(dict-pop!</code>&nbsp;<em>dto dictionary</em><code>)</code></p>
<p>Chooses an association from <em>dictionary</em> and returns three values: a dictionary that contains all associations of <em>dictionary</em> except the chosen one, and the key and the value of the chosen association. If the dictionary is ordered, the first association is chosen; otherwise the chosen association is arbitrary.</p>
<p>If dictionary contains no associations, it is an error.</p>
-<blockquote><pre>(dict-pop! dict) =&gt; # 3 values
+<blockquote><pre>(dict-pop! aed dict) =&gt; # 3 values
((3 . 4) (5 . 6))
1
2</pre></blockquote>
-<p><code>(dict-map!</code>&nbsp;<em>proc dictionary</em><code>)</code></p>
+<p><code>(dict-map!</code>&nbsp;<em>proc dto dictionary</em><code>)</code></p>
<p>Returns a dictionary similar to <em>dictionary</em> that maps each key of <em>dictionary</em> to the value that results from invoking <em>proc</em> on the corresponding key and value of <em>dictionary</em>.</p>
-<blockquote><pre>(dict-map! (lambda (k v) (cons v k)) dict) =&gt; ((2 . 1) (4 . 3) (6 . 5))</pre></blockquote>
-<p><code>(dict-filter!</code>&nbsp;<em>pred dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-map! (lambda (k v) (cons v k)) aed dict) =&gt; ((2 . 1) (4 . 3) (6 . 5))</pre></blockquote>
+<p><code>(dict-filter!</code>&nbsp;<em>pred dto dictionary</em><code>)</code></p>
<p>Returns a dictionary similar to <em>dictionary</em> that contains just the associations of <em>dictionary</em> that satisfy <em>pred</em> when it is invoked on the key and value of the association.</p>
-<blockquote><pre>(dict-filter! (lambda (k v) (= k 1)) dict) =&gt; ((1 . 2))</pre></blockquote>
-<p><code>(dict-remove!</code>&nbsp;<em>pred dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-filter! (lambda (k v) (= k 1)) aed dict) =&gt; ((1 . 2))</pre></blockquote>
+<p><code>(dict-remove!</code>&nbsp;<em>pred dto dictionary</em><code>)</code></p>
<p>Returns a dictionary that contains all the associations of <em>dictionary</em> except those that satisfy <em>pred</em> when called on the key and value.</p>
-<blockquote><pre>(dict-remove! (lambda (k) (= k 1)) dict) =&gt; ((3 . 4) (5 . 6))</pre></blockquote>
-<p><code>(dict-search!</code>&nbsp;<em>dictionary key failure success</em><code>)</code></p>
+<blockquote><pre>(dict-remove! (lambda (k) (= k 1)) aed dict) =&gt; ((3 . 4) (5 . 6))</pre></blockquote>
+<p><code>(dict-search!</code>&nbsp;<em>dto dictionary key failure success</em><code>)</code></p>
<p>This procedure is a workhorse for dictionary lookup, insert, and delete. The dictionary <em>dictionary</em> is searched for an association whose key is the same as <em>key</em> in the sense of <em>dictionary</em>. If one is not found, then the <em>failure</em> procedure is tail-called with two procedure arguments, <em>insert</em> and <em>ignore</em>, and is expected to tail-call one of them.</p>
<p>However, if such an association is found, then the <em>success</em> procedure is tail-called with the matching key of <em>dictionary</em>, the associated value, and two procedure arguments, <em>update</em> and <em>remove</em>, and is expected to tail-call one of them.</p>
<p>It is an error if the procedure arguments are invoked other than in tail position in the <em>failure</em> and <em>success</em> procedures. It is also an error if the <em>failure</em> and <em>success</em> procedures return to their implicit continuation without invoking one of their arguments.</p>
@@ -156,7 +162,7 @@ one for each of the four procedures:
(ignore 'foo))
(lambda args
(error))))
- (dict->alist dict)) => ((a . b))
+ (dict->alist aed dict)) => ((a . b))
value => 'foo
;; insert
@@ -167,8 +173,8 @@ one for each of the four procedures:
(insert 'd 'foo))
(lambda args
(`rror))))
- (dict-ref dict 'a)) => b
- (dict-ref dict 'c)) => 'd`
+ (dict-ref aed dict 'a)) => b
+ (dict-ref aed dict 'c)) => 'd`
value => foo
;; update
@@ -179,7 +185,7 @@ one for each of the four procedures:
(error))
(lambda (key value update delete)
(update 'a2 'b2 'foo))))
- (dict->alist dict) => ((a2 . b2)
+ (dict->alist aed dict) => ((a2 . b2)
value => foo
;; delete
@@ -190,72 +196,80 @@ one for each of the four procedures:
(error))
(lambda (key value update delete)
(delete 'foo))))
- (dict->alist dict)) => ((c . d))
+ (dict->alist aed dict)) => ((c . d))
value => foo
</pre></blockquote>
<h3 id="the-whole-dictionary">The whole dictionary</h3>
-<p><code>(dict-size</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<p><code>(dict-size</code>&nbsp;<em>dto dictionary</em><code>)</code></p>
<p>Returns an exact integer representing the number of associations in <em>dictionary</em>.</p>
-<blockquote><pre>(dict-size dict) =&gt; 0</pre></blockquote>
-<p><code>(dict-for-each</code>&nbsp;<em>proc dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-size aed dict) =&gt; 3</pre></blockquote>
+<p><code>(dict-for-each</code>&nbsp;<em>proc dto dictionary</em><code>)</code></p>
<p>Invokes <em>proc</em> on each key of <em>dictionary</em> and its corresponding value in that order. This procedure is used for doing operations on the whole dictionary. If the dictionary type is inherently ordered, associations are processed in the inherent order; otherwise in an arbitrary order. Returns an unspecified value.</p>
<blockquote><pre>(define (write-key key value) (write key))
-(dict-for-each write-key dict) =&gt; unspecified
+(dict-for-each write-key aed dict) =&gt; unspecified
; writes &quot;135&quot; to current output</pre></blockquote>
-<p><code>(dict-count</code>&nbsp;<em>pred dictionary</em><code>)</code></p>
+<p><code>(dict-count</code>&nbsp;<em>pred dto dictionary</em><code>)</code></p>
<p>Passes each association of dictionary as two arguments to <em>pred</em> and returns the number of times that <em>pred</em> returned true as an an exact integer.</p>
-<blockquote><pre>(dict-count dict (lambda (k v) (even? k))) =&gt; 0</pre></blockquote>
-<p><code>(dict-any</code>&nbsp;<em>pred dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-count aed dict (lambda (k v) (even? k))) =&gt; 0</pre></blockquote>
+<p><code>(dict-any</code>&nbsp;<em>pred dto dictionary</em><code>)</code></p>
<p>Passes each association of <em>dictionary</em> as two arguments to <em>pred</em> and returns the value of the first call to <em>pred</em> that returns true, after which no further calls are made. If the dictionary type is inherently ordered, associations are processed in the inherent order; otherwise in an arbitrary order. If all calls return false, <code>dict-any</code> returns false.</p>
<blockquote><pre>(define (both-even? k v) (and (even? k) (even? v)))
(dict-any both-even? &#39;((2 . 4) (3 . 5))) =&gt; #t
(dict-any both-even? &#39;((1 . 2) (3 . 4))) =&gt; #f</pre></blockquote>
-<p><code>(dict-every</code>&nbsp;<em>pred dictionary</em><code>)</code></p>
+<p><code>(dict-every</code>&nbsp;<em>pred dto dictionary</em><code>)</code></p>
<p>Passes each association of <em>dictionary</em> as two arguments to <em>pred</em> and returns <code>#f</code> after the first call to <em>pred</em> that returns false, after which no further calls are made. If the dictionary type is inherently ordered, associations are processed in the inherent order; otherwise in an arbitrary order. If all calls return true, <code>dict-any</code> returns the value of the last call, or <code>#t</code> if no calls are made.</p>
<blockquote><pre>(define (some-even? k v) (or (even? k) (even? v)))
(dict-every some-even? &#39;((2 . 3) (3 . 4))) =&gt; #t
(dict-every some-even? &#39;((1 . 3) (3 . 4))) =&gt; #f</pre></blockquote>
-<p><code>(dict-keys</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<p><code>(dict-keys</code>&nbsp;<em>dto dictionary</em><code>)</code></p>
<p>Returns a list of the keys of <em>dictionary</em>. If the dictionary type is inherently ordered, associations are processed in the inherent order; otherwise in an arbitrary order. The order may change when new elements are added to <em>dictionary</em>.</p>
-<blockquote><pre>(dict-keys dict) =&gt; (1 3 5)</pre></blockquote>
-<p><code>(dict-values</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-keys aed dict) =&gt; (1 3 5)</pre></blockquote>
+<p><code>(dict-values</code>&nbsp;<em>dto dictionary</em><code>)</code></p>
<p>Returns a list of the values of <em>dictionary</em>. The results returned by <code>dict-keys</code> and <code>dict-values</code> are not necessarily ordered consistently.</p>
-<blockquote><pre>(dict-values dict) =&gt; (2 4 6)</pre></blockquote>
-<p><code>(dict-entries</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-values aed dict) =&gt; (2 4 6)</pre></blockquote>
+<p><code>(dict-entries</code>&nbsp;<em>dto dictionary</em><code>)</code></p>
<p>Returns two values, the results of calling <code>dict-keys</code> and the result of calling <code>dict-values</code> on <em>dictionary</em>.</p>
-<blockquote><pre>(dict-entries dict) =&gt; ; 2 values
+<blockquote><pre>(dict-entries aed dict) =&gt; ; 2 values
(1 3 5)
(2 4 6)</pre></blockquote>
-<p><code>(dict-fold</code>&nbsp;<em>proc knil dictionary</em><code>)</code></p>
+<p><code>(dict-fold</code>&nbsp;<em>proc knil dto dictionary</em><code>)</code></p>
<p>Invokes <em>proc</em> on each association of <em>dictionary</em> with three arguments: the key of the association, the value of the association, and an accumulated result of the previous invocation. For the first invocation, <em>knil</em> is used as the third argument. Returns the result of the last invocation, or <em>knil</em> if there was no invocation.</p>
<blockquote><pre>(dict-fold + 0 &#39;((1 . 2) (3 . 4))) =&gt; 10</pre></blockquote>
-<p><code>(dict-map-&gt;list</code>&nbsp;<em>proc dictionary</em><code>)</code></p>
+<p><code>(dict-map-&gt;list</code>&nbsp;<em>proc dto dictionary</em><code>)</code></p>
<p>Returns a list of values that result from invoking <em>proc</em> on the keys and corresponding values of <em>dictionary</em>.</p>
-<blockquote><pre>(dict-map-&gt;list - dict) =&gt; (-1 -1 -1)</pre></blockquote>
-<p><code>(dict-&gt;alist</code>&nbsp;<em>dictionary</em><code>)</code></p>
+<blockquote><pre>(dict-map-&gt;list - aed dict) =&gt; (-1 -1 -1)</pre></blockquote>
+<p><code>(dict-&gt;alist</code>&nbsp;<em>dto dictionary</em><code>)</code></p>
<p>Returns an alist whose keys and values are the keys and values of <em>dictionary</em>.</p>
<blockquote><pre>; plist to alist
(dict-&gt;alist &#39;(1 2 3 4 5 6)) =&gt; ((1 . 2) (3 . 4) (5 . 6))</pre></blockquote>
-<h3 id="registering-dictionary-types">Registering dictionary types</h3>
-<p>The following procedure registers new dictionary types. It is an error to register a dictionary type whose instances return <code>#t</code> to any predicate already registered.</p>
-<p><code>(register-dictionary-type!</code>&nbsp;<em>arg</em> …<code>)</code></p>
-<p>Registers a new dictionary type, providing procedures that allow manipulation of dictionaries of that type. The <em>args</em> are alternately <em>procnames</em> and corresponding <em>procs</em>.</p>
-<p>A <em>procname</em> argument is a symbol which is the same as one of the procedures defined in this SRFI (other than <code>register-dictionary-type!</code> itself), and a <em>proc</em> argument is the specific procedure implementing it for this type. These procedures only need to handle the full argument list when defining <code>dict-ref</code> and <code>dict-update!</code>, as the other defaults have already been supplied by the framework.</p>
+<h3 id="dictionary-type-objects">Dictionary type objects</h3>
+<p><code>(make-dto</code>&nbsp;<em>arg</em> …<code>)</code></p>
+<p>Returns a new dictionary type providing procedures that allow manipulation of dictionaries of that type. The <em>args</em> are alternately <em>procnames</em> and corresponding <em>procs</em>.</p>
+<p>A <em>procname</em> argument is a symbol which is the same as one of the procedures defined in this SRFI (other than those in this section), and a <em>proc</em> argument is the specific procedure implementing it for this type. These procedures only need to handle a full-length argument list (except when defining <code>dict-ref</code> and <code>dict-update!</code>), as the other defaults have already been supplied by the framework.</p>
<p>Arguments for the six procedures <code>dictionary?</code>, <code>dict-size</code>, <code>dict-search!</code>, <code>dict-map!</code>, <code>dict-filter!</code>, and <code>dict-for-each</code> are required. The others are optional, but if provided can be more efficient than the versions automatically provided by the implementation of this SRFI.</p>
-<p>The following example is from the file <code>alist-impl.scm</code>
+<p>The following example is from the file <code>plist-impl.scm</code>
in the sample implementation; the procedures referred to are also in
that file.<p>
<blockquote><pre>
- (register-dictionary-type!
- 'dictionary? alist?
- 'dict-map! alist-map!
- 'dict-filter! alist-filter!
- 'dict-search! alist-search!
- 'dict-size alist-size
- 'dict-for-each alist-foreach
- 'dict->alist alist->alist))
+ (make-dictionary-type
+ 'dictionary? plist?
+ 'dict-map! plist-map!
+ 'dict-filter! plist-filter!
+ 'dict-search! plist-search!
+ 'dict-size plist-size
+ 'dict-for-each plist-foreach
+ 'dict->alist plist->alist)) =&gt; a DTO for plists
</pre></blockquote>
+<p><code>(make-alist-dto</code>&nbsp;<em>equal</em><code>)</code></p>
+<p>Returns a DTO for manipulating an alist using the equality predicate <em>equal</em>.</p>
+<blockquote><code>(make-alist-dto =) =&gt; a DTO for alists using numeric equality</code></blockquote>
+<p>The following DTOs are also exported from this SRFI:
+<code>srfi-69-dto</code>, <code>srfi-125-dto</code>, <code>srfi-126</code>,
+<code>srfi-146-dto</code>, <code>srfi-224-dto</code>, <code>plist-dto</code>,
+<code>alist-eqv-dto</code>, and <code>alist-equal-dto</code>.
+The last two provide DTOs for alists using <code>eqv?</code>
+and <code>equal?</code> respectively.</p>
<h2 id="implementation">Implementation</h2>
<p>The sample implementation is found in the GitHub repository.</p>