summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar John Cowan 2021-04-09 23:17:19 -0400
committerGravatar GitHub 2021-04-09 23:17:19 -0400
commitb597a37f11625794db49d612a26d7c09547ece29 (patch)
tree4bda2c4f57b691799382b5b97d034672918c9a4d
parentUpdate spec.md (diff)
WIP examples
-rw-r--r--spec.md180
1 files changed, 154 insertions, 26 deletions
diff --git a/spec.md b/spec.md
index 87563d2..3f73f77 100644
--- a/spec.md
+++ b/spec.md
@@ -60,6 +60,32 @@ Dictionaries are said in this SRFI to be *similar* if they are of the same
type and have the same [SRFI 128](http://srfi.schemers.org/srfi-128/srfi-128.html)
comparator.
+## Lists as dictionaries
+
+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.
+
+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 `eq?`.
+
+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 `equal?`.
+The examples in this SRFI use alists.
+
+In all other cases, lists are not treated as dictionaries
+unless an appropriate dictionary type has been registered.
+
## Predicates
`(dictionary? `*obj*`)`
@@ -67,12 +93,26 @@ comparator.
Returns `#t` if *obj* answers `#t` to some registered predicate,
and `#f` otherwise.
+```
+(define dict '((1 . 2) (3 . 4) (5 . 6)))
+(dictionary? dict) => #t
+```
+
`(dict-empty? `*dictionary*`)`
Returns `#t` if *dictionary* contains no associations
and `#f` if it does contain associations.
+```
+(dict-empty? '()) => #t
+(dict-empty? dict) => #f
+```
+
`(dict-contains? `*dictionary key*`)`
+```
+(dict-contains? dict 1) => #t
+(dict-contains? dict 2) => #f
+```
Returns `#t `if one of the keys of *dictionary* is the same as *key*
and `#f` otherwise.
@@ -89,12 +129,22 @@ then invokes the thunk *failure* and returns its result.
The default value of *failure* signals an error;
the default value of *success* is the identity procedure.
+```
+(dict-ref dict 1 (lambda () '() list) => (1) ; success wraps value in a list
+(dict-ref dict 2 (lambda () '() list)) => () ; failure returns empty list
+```
+
`(dict-ref/default `*dictionary key default*`)`
If *key* is the same as some key of *dictionary*
then returns the corresponding value.
If not, then returns *default*.
+```
+(dict-ref/default dict 1 #f) => 1
+(dict-ref/default dict 1 #f) => #f
+```
+
## Mutation
All these procedures are linear-update: that is, they may return a new
@@ -109,22 +159,44 @@ Returns a dictionary that contains all the associations of *dictionary*
plus those specified by *objs*, which alternate between keys and values.
If a key to be added already exists in *dictionary*, the new value prevails.
+```
+; alists are changed non-destructively
+(dict-set! dict 7 8) => ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
+(dict-set! dict 3 5) => ((1 . 2) (3 . 5) (5 . 6) ; may share last alist entry
+```
+
`(dict-adjoin! `dictionary obj ...`)`
Returns a dictionary that contains all the associations of *dictionary*
-plus those sp8ecified by *objs*, which alternate between keys and values.
+plus those specified by *objs*, which alternate between keys and values.
If a key to be added already exists in *dictionary*, the old value prevails.
+```
+; alists are changed non-destructively
+(dict-adjoin! dict 7 8) => ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
+(dict-adjoin! dict 3 5) => ((1 . 2) (3 . 5) (5 . 6) ; may share last alist entry
+```
+
`(dict-delete! `*dictionary key* ...`)`
Returns a dictionary that contains all the associations of *dictionary* except those
whose keys are the same as one of the *keys*.
+```
+; alists are changed non-destructively
+(dict-delete! dict 1 3) => ((7 . 8) (1 . 2) (3 . 4) (5 . 6))
+(dict-delete! dict 3 5) => ((1 . 2) (3 . 4) (5 . 6) ; may share whole alist
+```
+
`(dict-delete-all! `*dictionary keylist*`)`
Returns a dictionary with all the associations of *dictionary* except those whose
keys are the same as some member of *keylist*.
+```
+(dict-delete-all! dict '(1 3)) => ((5 . 6))
+```
+
`(dict-replace! `*dictionary key value*`)`
Returns a dictionary that
@@ -135,6 +207,11 @@ defined by the pair *key* and *value*.
If there is no such key in *dictionary*,
then dictionary is returned unchanged.
+```
+(dict-replace! dict 1 3) => ((1 . 3) (3 . 4) (5 . 6))
+(dict-replace! dict 2 3) => ((1 . 2) (3 . 4) (5 . 6))
+```
+
`(dict-intern! `dictionary key failure`)`
Extracts the value associated with the key in *dictionary* that is the same as *key*,
@@ -146,6 +223,15 @@ a dictionary that contains all the associations of *dictionary*
and in addition a new association that maps *key* to the result of invoking *failure*,
and the result of invoking *failure*.
+```
+(dict-intern! dict 1 (lambda () #f)) => ; 2 values
+ ((1 . 2) (3 . 4) (5 . 6))
+ 3
+(dict-intern! dict 2 (lambda () #f)) => ; 2 values
+ ((2 . #f) (1 . 2) (3 . 4) (5 . 6))
+ #f
+```
+
`(dict-update! `*dictionary key updater* [*failure* [*success*] ]`)`
Retrieves the value of *key* as if by `dict-ref`,
@@ -174,22 +260,41 @@ If dictionary contains no associations and *failure* is supplied,
then the thunk *failure* is invoked and its values returned.
Otherwise, it is an error.
+```
+(dict-pop! dict) => # 3 values
+ ((3 . 4) (5 . 6))
+ 1
+ 2
+```
+
`(dict-map! `*proc dictionary*`)`
Returns a dictionary similar to *dictionary* that maps each key of *dictionary*
to the value that results
from invoking *proc* on the corresponding key and value of *dictionary*.
+```
+(dict-map! (lambda (k v) (cons v k)) dict) => ((2 . 1) (4 . 3) (6 . 5))
+```
+
`(dict-filter! `*pred dictionary*`)`
Returns a dictionary similar to *dictionary* that contains just the associations of *dictionary*
that satisfy *pred* when it is invoked on the key and value of the association.
+```
+(dict-filter (lambda (x) (= x 1)) dict) => ((1 . 2))
+```
+
`(dict-remove! `*pred dictionary*`)`
Returns a dictionary that contains all the associations of *dictionary*
except those that satisfy *pred* when called on the key and value.
+```
+(dict-remove (lambda (x) (= x 1)) dict) => ((3 . 4) (5 . 6))
+```
+
`(dict-search! `*dictionary key failure success*`)`
This procedure is a workhorse for dictionary lookup, insert, and delete.
@@ -242,6 +347,10 @@ In all cases, *obj* is returned as a second value.
Returns an exact integer representing the number of associations in *dictionary*.
+```
+(dict-size dict) => 0
+```
+
`(dict-for-each `*proc dictionary*`)`
Invokes *proc* on each key of *dictionary* and its corresponding value in that order.
@@ -250,12 +359,21 @@ If the dictionary type is inherently ordered, associations are processed in the
inherent order; otherwise in an arbitrary order.
Returns an unspecified value.
+```
+(dict-for-each write dict) => unspecified
+ ; writes "135" to current output
+```
+
`(dict-count `*pred dictionary*`)`
Passes each association of dictionary as two arguments to *pred*
and returns the number of times
that *pred* returned true as an an exact integer.
+```
+(dict-count dict (lambda (k v) (even? k) => 0
+```
+
`(dict-any `*pred dictionary*`)`
Passes each association of *dictionary* as two arguments to *pred*
@@ -264,6 +382,10 @@ If the dictionary type is inherently ordered, associations are processed in the
inherent order; otherwise in an arbitrary order.
If all calls return false, `dict-any` returns false.
+```
+FIXME
+```
+
`(dict-every `*pred dictionary*`)`
Passes each association of *dictionary* as two arguments to *pred*
@@ -273,6 +395,10 @@ inherent order; otherwise in an arbitrary order.
If all calls return true, `dict-any` returns the value of the last call,
or `#t` if no calls are made.
+```
+FIXME
+```
+
`(dict-keys `*dictionary*`)`
Returns a list of the keys of *dictionary*.
@@ -280,16 +406,30 @@ 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 *dictionary*.
+```
+(dict-keys dict) => (1 3 5)
+```
+
`(dict-values `*dictionary*`)`
Returns a list of the values of *dictionary*. The results returned
by `dict-keys` and `dict-values` are ordered consistently.
+```
+(dict-values dict) => (2 4 6)
+```
+
`(dict-entries `*dictionary*`)`
Returns two values, the result of calling `dict-keys` and the
result of calling `dict-values` on *dictionary*.
+```
+(dict-entries dict) => ; 2 values
+ (1 3 5)
+ (2 4 6)
+```
+
`(dict-fold `*proc knil dictionary*`)`
Invokes *proc* on each association of *dictionary* with three arguments:
@@ -299,15 +439,28 @@ For the first invocation, *knil* is used as the third argument.
Returns the result of the last invocation,
or *knil* if there was no invocation.
+```
+FIXME
+```
+
`(dict-map->list `*proc dictionary*`)`
Returns a list of values that result from invoking *proc*
on the keys and corresponding values of *dictionary*.
+```
+(dict-map->list - dict) => (-1 -1 -1)
+```
+
`(dict->alist `*dictionary*`)`
Returns an alist whose keys and values are the keys and values of *dictionary*.
+```
+; plist to alist
+(dict->alist '(1 2 3 4 5 6)) => ((1 . 2) (3 . 4) (5 . 6))
+```
+
## Registering dictionary types
The following procedure registers new dictionary types.
@@ -333,31 +486,6 @@ Arguments for the six procedures `dictionary?`, `dict-size`,
The others are optional, but if provided can be more efficient
than the versions automatically provided by the implementation of this SRFI.
-## Lists as dictionaries
-
-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.
-
-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 `eq?`.
-
-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 `equal?`.
-
-In all other cases, lists are not treated as dictionaries
-unless an appropriate dictionary type has been registered.
-
## Implementation
The sample implementation of this SRFI can be found in its repository.