diff options
| author | 2021-04-09 23:17:19 -0400 | |
|---|---|---|
| committer | 2021-04-09 23:17:19 -0400 | |
| commit | b597a37f11625794db49d612a26d7c09547ece29 (patch) | |
| tree | 4bda2c4f57b691799382b5b97d034672918c9a4d | |
| parent | Update spec.md (diff) | |
WIP examples
| -rw-r--r-- | spec.md | 180 |
1 files changed, 154 insertions, 26 deletions
@@ -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. |
