On this page:
4.18.1 Dictionary Predicates and Contracts
dict?
dict-implements?
dict-implements/  c
dict-mutable?
dict-can-remove-keys?
dict-can-functional-set?
4.18.2 Generic Dictionary Interface
gen:  dict
prop:  dict
4.18.2.1 Primitive Dictionary Methods
dict-ref
dict-set!
dict-set
dict-remove!
dict-remove
dict-iterate-first
dict-iterate-next
dict-iterate-key
dict-iterate-value
4.18.2.2 Derived Dictionary Methods
dict-has-key?
dict-set*!
dict-set*
dict-ref!
dict-update!
dict-update
dict-map
dict-map/  copy
dict-for-each
dict-empty?
dict-count
dict-copy
dict-clear
dict-clear!
dict-keys
dict-values
dict->list
4.18.3 Dictionary Sequences
in-dict
in-dict-keys
in-dict-values
in-dict-pairs
4.18.4 Contracted Dictionaries
prop:  dict/  contract
dict-key-contract
dict-value-contract
dict-iter-contract
4.18.5 Custom Hash Tables
define-custom-hash-types
make-custom-hash-types
make-custom-hash
make-weak-custom-hash
make-immutable-custom-hash
4.18.6 Passing Keyword Arguments in Dictionaries
keyword-apply/  dict

4.18 Dictionaries🔗

dictionary(字典)是一种将键映射到值的数据类型的实例。以下数据类型都是字典:

  • hash tables;

  • vectors (using only exact integers as keys);

  • lists of pairs 作为 association list(关联列表),使用 equal? 比较键,键必须互不相同;以及

  • 实现了 gen:dict generic interfacestructures

当 pair 的列表用作 association list 但键不互不相同时(因此它不是真正的 association list),dict-refdict-remove 等操作作用于键的第一个实例,而 dict-mapdict-keys 等操作则为键的每个实例产生一个元素。

 (require racket/dict) package: base
The bindings documented in this section are provided by the racket/dict and racket libraries, but not racket/base.

4.18.1 Dictionary Predicates and Contracts🔗

procedure

(dict? v)  boolean?

  v : any/c
如果 v 是一个 dictionary,返回 #t,否则返回 #f

注意,dict? 对 pair 不是常数时间的测试,因为检查 v 是否是 association list 可能需要遍历整个列表。

Examples:
> (dict? #hash((a . "apple")))

#t

> (dict? '#("apple" "banana"))

#t

> (dict? '("apple" "banana"))

#f

> (dict? '((a . "apple") (b . "banana")))

#t

procedure

(dict-implements? d sym ...)  boolean?

  d : dict?
  sym : symbol?
如果 d 实现了 gen:dict 中由 sym 命名的所有方法,返回 #t;否则返回 #f。回退实现不影响结果;d 可能通过回退实现支持给定方法但仍返回 #f

Examples:
> (dict-implements? (hash 'a "apple") 'dict-set!)

#f

> (dict-implements? (make-hash '((a . "apple") (b . "banana"))) 'dict-set!)

#t

> (dict-implements? (make-hash '((b . "banana") (a . "apple"))) 'dict-remove!)

#t

> (dict-implements? (vector "apple" "banana") 'dict-set!)

#t

> (dict-implements? (vector 'a 'b) 'dict-remove!)

#f

> (dict-implements? (vector 'a "apple") 'dict-set! 'dict-remove!)

#f

procedure

(dict-implements/c sym ...)  flat-contract?

  sym : symbol?
识别支持 gen:dict 中由 sym 命名的所有方法的字典。注意,生成的 contract 与 hash/c 不同,而更接近 dict-implements?

Examples:
> (struct deformed-dict ()
    #:methods gen:dict [])
> (define/contract good-dict
    (dict-implements/c)
    (deformed-dict))
> (define/contract bad-dict
    (dict-implements/c 'dict-ref)
    (deformed-dict))

bad-dict: broke its own contract

  promised: (dict-implements/c dict-ref)

  produced: #<deformed-dict>

  in: (dict-implements/c dict-ref)

  contract from: (definition bad-dict)

  blaming: (definition bad-dict)

   (assuming the contract is correct)

  at: eval:14:0

procedure

(dict-mutable? d)  boolean?

  d : dict?
如果 d 可通过 dict-set! 修改,返回 #t,否则返回 #f

等价于 (dict-implements? d 'dict-set!)

Examples:
> (dict-mutable? #hash((a . "apple")))

#f

> (dict-mutable? (make-hash))

#t

> (dict-mutable? '#("apple" "banana"))

#f

> (dict-mutable? (vector "apple" "banana"))

#t

> (dict-mutable? '((a . "apple") (b . "banana")))

#f

procedure

(dict-can-remove-keys? d)  boolean?

  d : dict?
如果 d 支持通过 dict-remove! 和/或 dict-remove 删除映射,返回 #t,否则返回 #f

等价于 (or (dict-implements? d 'dict-remove!) (dict-implements? d 'dict-remove))

Examples:
> (dict-can-remove-keys? #hash((a . "apple")))

#t

> (dict-can-remove-keys? '#("apple" "banana"))

#f

> (dict-can-remove-keys? '((a . "apple") (b . "banana")))

#t

procedure

(dict-can-functional-set? d)  boolean?

  d : dict?
如果 d 支持通过 dict-set 进行函数式更新,返回 #t,否则返回 #f

等价于 (dict-implements? d 'dict-set)

Examples:
> (dict-can-functional-set? #hash((a . "apple")))

#t

> (dict-can-functional-set? (make-hash))

#f

> (dict-can-functional-set? '#("apple" "banana"))

#f

> (dict-can-functional-set? '((a . "apple") (b . "banana")))

#t

4.18.2 Generic Dictionary Interface🔗

syntax

gen:dict

一个 generic interface(参见 Generic Interfaces),通过 struct 定义的 #:methods 选项为结构类型提供字典方法实现。此接口可用于实现 Primitive Dictionary MethodsDerived Dictionary Methods 中记录的任何方法。

Examples:
> (struct alist (v)
    #:methods gen:dict
    [(define (dict-ref dict key
                       [default (lambda () (error "key not found" key))])
       (cond [(assoc key (alist-v dict)) => cdr]
             [else (if (procedure? default) (default) default)]))
     (define (dict-set dict key val)
       (alist (cons (cons key val) (alist-v dict))))
     (define (dict-remove dict key)
       (define al (alist-v dict))
       (alist (remove* (filter (λ (p) (equal? (car p) key)) al) al)))
     (define (dict-count dict)
       (length (remove-duplicates (alist-v dict) #:key car)))])
; etc. other methods
> (define d1 (alist '((1 . a) (2 . b))))
> (dict? d1)

#t

> (dict-ref d1 1)

'a

> (dict-remove d1 1)

#<alist>

一个结构类型属性,用于定义字典 API 的自定义扩展。不建议使用 prop:dict 属性;请改用 gen:dict generic interface。接受一个包含 10 个方法实现的向量:

4.18.2.1 Primitive Dictionary Methods🔗

这些 gen:dict 方法没有回退实现;仅支持直接实现它们的字典类型。

procedure

(dict-ref dict key [failure-result])  any

  dict : dict?
  key : any/c
  failure-result : failure-result/c
   = (lambda () (raise (make-exn:fail ....)))
返回 dictkey 对应的值。如果未找到 key 的值,则 failure-result 决定结果:

  • 如果 failure-result 是一个过程,则通过尾调用以无参数方式调用它来产生结果。

  • 否则,failure-result 作为结果返回。

Examples:
> (dict-ref #hash((a . "apple") (b . "beer")) 'a)

"apple"

> (dict-ref #hash((a . "apple") (b . "beer")) 'c)

hash-ref: no value found for key

  key: 'c

> (dict-ref #hash((a . "apple") (b . "beer")) 'c #f)

#f

> (dict-ref '((a . "apple") (b . "banana")) 'b)

"banana"

> (dict-ref #("apple" "banana") 1)

"banana"

> (dict-ref #("apple" "banana") 3 #f)

#f

> (dict-ref #("apple" "banana") -3 #f)

dict-ref: contract violation

  expected: natural?

  given: -3

  in: the k argument of

      (->i

       ((d dict?) (k (d) (dict-key-contract d)))

       ((default any/c))

       any)

  contract from: <collects>/racket/dict.rkt

  blaming: top-level

   (assuming the contract is correct)

  at: <collects>/racket/dict.rkt:182:2

procedure

(dict-set! dict key v)  void?

  dict : (and/c dict? (not/c immutable?))
  key : any/c
  v : any/c
dict 中将 key 映射到 v,覆盖 key 的任何现有映射。如果 dict 不可变或 key 不是该字典允许的键(例如,当 dictvector 时不是适当范围内的精确整数),更新可能抛出 exn:fail:contract 异常而失败。

Examples:
> (define h (make-hash))
> (dict-set! h 'a "apple")
> h

'#hash((a . "apple"))

> (define v (vector #f #f #f))
> (dict-set! v 0 "apple")
> v

'#("apple" #f #f)

procedure

(dict-set dict key v)  (and/c dict? immutable?)

  dict : (and/c dict? immutable?)
  key : any/c
  v : any/c
通过将 key 映射到 v 来函数式扩展 dict,覆盖 key 的任何现有映射,并返回扩展后的字典。如果 dict 不支持函数式扩展或 key 不是该字典允许的键,更新可能抛出 exn:fail:contract 异常而失败。

Examples:
> (dict-set #hash() 'a "apple")

'#hash((a . "apple"))

> (dict-set #hash((a . "apple") (b . "beer")) 'b "banana")

'#hash((a . "apple") (b . "banana"))

> (dict-set '() 'a "apple")

'((a . "apple"))

> (dict-set '((a . "apple") (b . "beer")) 'b "banana")

'((a . "apple") (b . "banana"))

procedure

(dict-remove! dict key)  void?

  dict : (and/c dict? (not/c immutable?))
  key : any/c
删除 dictkey 的任何现有映射。如果 dict 不可变或不支持删除键(例如 vectors 的情况),更新可能失败。

Examples:
> (define h (make-hash))
> (dict-set! h 'a "apple")
> h

'#hash((a . "apple"))

> (dict-remove! h 'a)
> h

'#hash()

procedure

(dict-remove dict key)  (and/c dict? immutable?)

  dict : (and/c dict? immutable?)
  key : any/c
函数式删除 dictkey 的任何现有映射,返回新的字典。如果 dict 不支持函数式更新或不支持删除键,更新可能失败。

Examples:
> (define h #hash())
> (define h (dict-set h 'a "apple"))
> h

'#hash((a . "apple"))

> (dict-remove h 'a)

'#hash()

> h

'#hash((a . "apple"))

> (dict-remove h 'z)

'#hash((a . "apple"))

> (dict-remove '((a . "apple") (b . "banana")) 'a)

'((b . "banana"))

procedure

(dict-iterate-first dict)  any/c

  dict : dict?
如果 dict 不包含元素,返回 #f,否则返回一个非 #f 的值作为字典表中第一个元素的索引;“first” 指字典元素的未指定排序。对于可变的 dict,只要没有向 dict 添加或删除映射,此索引保证指向第一个元素。

Examples:
> (dict-iterate-first #hash((a . "apple") (b . "banana")))

0

> (dict-iterate-first #hash())

#f

> (dict-iterate-first #("apple" "banana"))

0

> (dict-iterate-first '((a . "apple") (b . "banana")))

#<assoc-iter>

procedure

(dict-iterate-next dict pos)  any/c

  dict : dict?
  pos : any/c
返回 dictpos 索引之后的元素的索引(非 #f),如果 pos 指向 dict 的最后一个元素则返回 #f。如果 pos 不是有效索引,则抛出 exn:fail:contract exception is raised 异常。对于可变的 dict,只要没有添加或删除元素,结果索引保证指向其元素。dict-iterate-next 操作应为常数时间。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (define i (dict-iterate-first h))
> i

0

> (dict-iterate-next h i)

1

> (dict-iterate-next h (dict-iterate-next h i))

#f

procedure

(dict-iterate-key dict pos)  any

  dict : dict?
  pos : any/c
返回 dict 中索引 pos 处元素的键。如果 pos 不是 dict 的有效索引,则抛出 exn:fail:contract exception is raised 异常。dict-iterate-key 操作应为常数时间。

Examples:
> (define h '((a . "apple") (b . "banana")))
> (define i (dict-iterate-first h))
> (dict-iterate-key h i)

'a

> (dict-iterate-key h (dict-iterate-next h i))

'b

procedure

(dict-iterate-value dict pos)  any

  dict : dict?
  pos : any/c
返回 dict 中索引 pos 处元素的值。如果 pos 不是 dict 的有效索引,则抛出 exn:fail:contract exception is raised 异常。dict-iterate-key 操作应为常数时间。

Examples:
> (define h '((a . "apple") (b . "banana")))
> (define i (dict-iterate-first h))
> (dict-iterate-value h i)

"apple"

> (dict-iterate-value h (dict-iterate-next h i))

"banana"

4.18.2.2 Derived Dictionary Methods🔗

这些 gen:dict 方法基于其他方法有回退实现;即使未直接实现它们的字典类型也可能支持这些方法。

procedure

(dict-has-key? dict key)  boolean?

  dict : dict?
  key : any/c
如果 dict 包含给定 key 的值,返回 #t,否则返回 #f

任何实现了 dict-refdict 都支持此方法。

Examples:
> (dict-has-key? #hash((a . "apple") (b . "beer")) 'a)

#t

> (dict-has-key? #hash((a . "apple") (b . "beer")) 'c)

#f

> (dict-has-key? '((a . "apple") (b . "banana")) 'b)

#t

> (dict-has-key? #("apple" "banana") 1)

#t

> (dict-has-key? #("apple" "banana") 3)

#f

> (dict-has-key? #("apple" "banana") -3)

#f

procedure

(dict-set*! dict key v ... ...)  void?

  dict : (and/c dict? (not/c immutable?))
  key : any/c
  v : any/c
dict 中将每个 key 映射到对应的 v,覆盖每个 key 的任何现有映射。如果 dict 不可变或任何 key 不是该字典允许的键(例如,当 dictvector 时不是适当范围内的精确整数),更新可能抛出 exn:fail:contract 异常而失败。更新从左到右进行,因此后面的映射覆盖前面的映射。

任何实现了 dict-set!dict 都支持此方法。

Examples:
> (define h (make-hash))
> (dict-set*! h 'a "apple" 'b "banana")
> h

'#hash((a . "apple") (b . "banana"))

> (define v1 (vector #f #f #f))
> (dict-set*! v1 0 "apple" 1 "banana")
> v1

'#("apple" "banana" #f)

> (define v2 (vector #f #f #f))
> (dict-set*! v2 0 "apple" 0 "banana")
> v2

'#("banana" #f #f)

procedure

(dict-set* dict key v ... ...)  (and/c dict? immutable?)

  dict : (and/c dict? immutable?)
  key : any/c
  v : any/c
通过将每个 key 映射到对应的 v 来函数式扩展 dict,覆盖每个 key 的任何现有映射,并返回扩展后的字典。如果 dict 不支持函数式扩展或任何 key 不是该字典允许的键,更新可能抛出 exn:fail:contract 异常而失败。更新从左到右进行,因此后面的映射覆盖前面的映射。

任何实现了 dict-setdict 都支持此方法。

Examples:
> (dict-set* #hash() 'a "apple" 'b "beer")

'#hash((a . "apple") (b . "beer"))

> (dict-set* #hash((a . "apple") (b . "beer")) 'b "banana" 'a "anchor")

'#hash((a . "anchor") (b . "banana"))

> (dict-set* '() 'a "apple" 'b "beer")

'((a . "apple") (b . "beer"))

> (dict-set* '((a . "apple") (b . "beer")) 'b "banana" 'a "anchor")

'((a . "anchor") (b . "banana"))

> (dict-set* '((a . "apple") (b . "beer")) 'b "banana" 'b "ballistic")

'((a . "apple") (b . "ballistic"))

procedure

(dict-ref! dict key to-set)  any

  dict : dict?
  key : any/c
  to-set : any/c
返回 dictkey 对应的值。如果未找到 key 的值,则 to-setdict-ref 中一样决定结果(即它可以是计算值的 thunk 或普通值),并且此结果被存储在 dict 中对应的 key。(注意,如果 to-set 是 thunk,它不在尾位置被调用。)

任何实现了 dict-refdict-set!dict 都支持此方法。

Examples:
> (dict-ref! (make-hasheq '((a . "apple") (b . "beer"))) 'a #f)

"apple"

> (dict-ref! (make-hasheq '((a . "apple") (b . "beer"))) 'c 'cabbage)

'cabbage

> (define h (make-hasheq '((a . "apple") (b . "beer"))))
> (dict-ref h 'c)

hash-ref: no value found for key

  key: 'c

> (dict-ref! h 'c (λ () 'cabbage))

'cabbage

> (dict-ref h 'c)

'cabbage

procedure

(dict-update! dict    
  key    
  updater    
  [failure-result])  void?
  dict : (and/c dict? (not/c immutable?))
  key : any/c
  updater : (any/c . -> . any/c)
  failure-result : failure-result/c
   = (lambda () (raise (make-exn:fail ....)))
组合 dict-refdict-set! 来更新 dict 中的现有映射,当 key 的映射不存在时,可选的 failure-result 参数如 dict-ref 中一样使用。

任何实现了 dict-refdict-set!dict 都支持此方法。

Examples:
> (define h (make-hash))
> (dict-update! h 'a add1)

hash-update!: no value found for key: 'a

> (dict-update! h 'a add1 0)
> h

'#hash((a . 1))

> (define v (vector #f #f #f))
> (dict-update! v 0 not)
> v

'#(#t #f #f)

procedure

(dict-update dict key updater [failure-result])

  (and/c dict? immutable?)
  dict : dict?
  key : any/c
  updater : (any/c . -> . any/c)
  failure-result : failure-result/c
   = (lambda () (raise (make-exn:fail ....)))
组合 dict-refdict-set 来函数式更新 dict 中的现有映射,当 key 的映射不存在时,可选的 failure-result 参数如 dict-ref 中一样使用。

任何实现了 dict-refdict-setdict 都支持此方法。

Examples:
> (dict-update #hash() 'a add1)

hash-update: no value found for key: 'a

> (dict-update #hash() 'a add1 0)

'#hash((a . 1))

> (dict-update #hash((a . "apple") (b . "beer")) 'b string-length)

'#hash((a . "apple") (b . 4))

procedure

(dict-map dict proc)  (listof any/c)

  dict : dict?
  proc : (any/c any/c . -> . any/c)
以未指定的顺序对 dict 中的每个元素应用过程 proc,将结果累积到列表中。过程 proc 每次被调用时接收一个键及其值。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-valuedict 都支持此方法。

Example:
> (dict-map #hash((a . "apple") (b . "banana")) vector)

'(#(b "banana") #(a "apple"))

procedure

(dict-map/copy dict proc)  dict?

  dict : dict?
  proc : (any/c any/c . -> . (values any/c any/c))
以未指定的顺序对 dict 中的每个元素应用过程 proc,将结果累积到同类型的字典中。过程 proc 每次被调用时接收一个键及其值,必须返回对应的键和值。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-value,以及 dict-setdict-clear,或 dict-set!dict-copydict-clear!dict 都支持此方法。

Example:
> (dict-map/copy #hash((a . "apple") (b . "banana")) (lambda (k v) (values k (string-upcase v))))

'#hash((a . "APPLE") (b . "BANANA"))

Added in version 8.5.0.2 of package base.

procedure

(dict-for-each dict proc)  void?

  dict : dict?
  proc : (any/c any/c . -> . any)
以未指定的顺序对 dict 中的每个元素应用 proc(为了 proc 的副作用)。过程 proc 每次被调用时接收一个键及其值。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-valuedict 都支持此方法。

Example:
> (dict-for-each #hash((a . "apple") (b . "banana"))
                 (lambda (k v)
                   (printf "~a = ~s\n" k v)))

b = "banana"

a = "apple"

procedure

(dict-empty? dict)  boolean?

  dict : dict?
报告 dict 是否为空。

任何实现了 dict-iterate-firstdict 都支持此方法。

Examples:
> (dict-empty? #hash((a . "apple") (b . "banana")))

#f

> (dict-empty? (vector))

#t

procedure

(dict-count dict)  exact-nonnegative-integer?

  dict : dict?
返回 dict 映射的键数量,通常为常数时间。

任何实现了 dict-iterate-firstdict-iterate-nextdict 都支持此方法。

Examples:
> (dict-count #hash((a . "apple") (b . "banana")))

2

> (dict-count #("apple" "banana"))

2

procedure

(dict-copy dict)  dict?

  dict : dict?
产生一个新的、可变的字典,与 dict 类型相同且具有相同的键/值关联。

任何实现了 dict-cleardict-set!dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-valuedict 都支持此方法。

Examples:
> (define original (vector "apple" "banana"))
> (define copy (dict-copy original))
> original

'#("apple" "banana")

> copy

'#("apple" "banana")

> (dict-set! copy 1 "carrot")
> original

'#("apple" "banana")

> copy

'#("apple" "carrot")

procedure

(dict-clear dict)  dict?

  dict : dict?
产生一个与 dict 类型相同的空字典。如果 dict 是可变的,结果必须是一个新字典。

任何支持 dict-removedict-iterate-firstdict-iterate-nextdict-iterate-keydict 都支持此方法。

Examples:
> (dict-clear #hash((a . "apple") ("banana" . b)))

'#hash()

> (dict-clear '((1 . two) (three . "four")))

'()

procedure

(dict-clear! dict)  void?

  dict : dict?
删除 dict 中所有的键/值关联。

任何支持 dict-remove!dict-iterate-firstdict-iterate-keydict 都支持此方法。

Examples:
> (define table (make-hash))
> (dict-set! table 'a "apple")
> (dict-set! table "banana" 'b)
> table

'#hash((a . "apple") ("banana" . b))

> (dict-clear! table)
> table

'#hash()

procedure

(dict-keys dict)  list?

  dict : dict?
以未指定的顺序返回 dict 中键的列表。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (dict-keys h)

'(b a)

procedure

(dict-values dict)  list?

  dict : dict?
以未指定的顺序返回 dict 中值的列表。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-valuedict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (dict-values h)

'("banana" "apple")

procedure

(dict->list dict)  list?

  dict : dict?
以未指定的顺序返回 dict 中关联的列表。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-valuedict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (dict->list h)

'((b . "banana") (a . "apple"))

4.18.3 Dictionary Sequences🔗

procedure

(in-dict dict)  sequence?

  dict : dict?
返回一个 sequence,其中每个元素是两个值:dict 中的一个键和对应的值。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-valuedict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (for/list ([(k v) (in-dict h)])
    (format "~a = ~s" k v))

'("b = \"banana\"" "a = \"apple\"")

procedure

(in-dict-keys dict)  sequence?

  dict : dict?
返回一个序列,其元素为 dict 的键。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (for/list ([k (in-dict-keys h)])
    k)

'(b a)

procedure

(in-dict-values dict)  sequence?

  dict : dict?
返回一个序列,其元素为 dict 的值。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-valuedict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (for/list ([v (in-dict-values h)])
    v)

'("banana" "apple")

procedure

(in-dict-pairs dict)  sequence?

  dict : dict?
返回一个序列,其元素为 pair,每个包含 dict 中的一个键及其值(与使用 in-dict 不同,后者将每个元素的键和值作为单独的值获取)。

任何实现了 dict-iterate-firstdict-iterate-nextdict-iterate-keydict-iterate-valuedict 都支持此方法。

Examples:
> (define h #hash((a . "apple") (b . "banana")))
> (for/list ([p (in-dict-pairs h)])
    p)

'((b . "banana") (a . "apple"))

4.18.4 Contracted Dictionaries🔗

一个结构类型属性,用于定义带有 contract 的字典。与 prop:dict/contract 关联的值必须是两个不可变向量的列表:

(list dict-vector
      (vector type-key-contract
              type-value-contract
              type-iter-contract
              instance-key-contract
              instance-value-contract
              instance-iter-contract))

第一个向量必须是包含 10 个过程的向量,匹配 gen:dict generic interface(此外,它必须是不可变向量)。第二个向量必须包含六个元素;前三个分别是字典类型的键、值和位置的 contract。后三个是 #f 或用于从字典实例中提取 contract 的过程。

procedure

(dict-key-contract d)  contract?

  d : dict?

procedure

(dict-value-contract d)  contract?

  d : dict?

procedure

(dict-iter-contract d)  contract?

  d : dict?
如果 d 实现了 prop:dict/contract 接口,分别返回 d 对其键、值或迭代器施加的 contract。

4.18.5 Custom Hash Tables🔗

syntax

(define-custom-hash-types name
                          optional-predicate
                          comparison-expr
                          optional-hash-functions)
 
optional-predicate = 
  | #:key? predicate-expr
     
optional-hash-functions = 
  | hash1-expr
  | hash1-expr hash2-expr
基于给定的比较 comparison-expr、hash 函数 hash1-exprhash2-expr,以及键谓词 predicate-expr 创建新的字典类型;这些函数的接口与 make-custom-hash-types 中的相同。新字典类型有三种变体:不可变、键强引用的可变和键弱引用的可变。

定义七个名称:

  • name? 识别新类型的实例,

  • immutable-name? 识别新类型的不可变实例,

  • mutable-name? 识别新类型的键强引用可变实例,

  • weak-name? 识别新类型的键弱引用可变实例,

  • make-immutable-name 构造新类型的不可变实例,

  • make-mutable-name 构造新类型的键强引用可变实例,以及

  • make-weak-name 构造新类型的键弱引用可变实例。

所有构造函数都接受一个字典作为可选参数,提供初始键/值对。

Examples:
> (define-custom-hash-types string-hash
                            #:key? string?
                            string=?
                            string-length)
> (define imm
    (make-immutable-string-hash
     '(("apple" . a) ("banana" . b))))
> (define mut
    (make-mutable-string-hash
     '(("apple" . a) ("banana" . b))))
> (dict? imm)

#t

> (dict? mut)

#t

> (string-hash? imm)

#t

> (string-hash? mut)

#t

> (immutable-string-hash? imm)

#t

> (immutable-string-hash? mut)

#f

> (dict-ref imm "apple")

'a

> (dict-ref mut "banana")

'b

> (dict-set! mut "banana" 'berry)
> (dict-ref mut "banana")

'berry

> (equal? imm mut)

#f

> (equal? (dict-remove (dict-remove imm "apple") "banana")
          (make-immutable-string-hash))

#t

procedure

(make-custom-hash-types eql?    
  [hash1    
  hash2    
  #:key? key?    
  #:name name    
  #:for who])  
(any/c . -> . boolean?)
(any/c . -> . boolean?)
(any/c . -> . boolean?)
(any/c . -> . boolean?)
(->* [] [dict?] dict?)
(->* [] [dict?] dict?)
(->* [] [dict?] dict?)
  eql? : 
(or/c (any/c any/c . -> . any/c)
      (any/c any/c (any/c any/c . -> . any/c) . -> . any/c))
  hash1 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  hash2 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  key? : (any/c . -> . boolean?) = (const #true)
  name : symbol? = 'custom-hash
  who : symbol? = 'make-custom-hash-types
基于给定的比较函数 eql?、hash 函数 hash1hash2,以及谓词 key? 创建新的字典类型。新字典类型有不可变、键强引用可变和键弱引用可变的变体。给定的 name 用于打印新字典类型的实例,符号 who 用于报告错误。

比较函数 eql? 可以接受 2 或 3 个参数。如果接受 2 个参数,则给定两个键来比较它们。如果接受 3 个参数且不接受 2 个参数,则还给定一个递归比较函数,用于在比较键的子部分时处理数据循环。

hash 函数 hash1hash2 可以接受 1 或 2 个参数。如果任一 hash 函数接受 1 个参数,则将其应用于键来计算对应的 hash 值。如果任一 hash 函数接受 2 个参数且不接受 1 个参数,则还给定一个递归 hash 函数,用于在计算键的子部分的 hash 值时处理数据循环。

谓词 key? 必须接受 1 个参数,用于识别新字典类型的有效键。

产生七个值:

  • 识别新字典类型所有实例的谓词,

  • 识别不可变实例的谓词,

  • 识别可变实例的谓词,

  • 识别弱引用实例的谓词,

  • 不可变实例的构造函数,

  • 可变实例的构造函数,以及

  • 弱引用实例的构造函数。

参见 define-custom-hash-types 获取示例。

procedure

(make-custom-hash eql?    
  [hash1    
  hash2    
  #:key? key?])  dict?
  eql? : 
(or/c (any/c any/c . -> . any/c)
      (any/c any/c (any/c any/c . -> . any/c) . -> . any/c))
  hash1 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  hash2 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  key? : (any/c . -> . boolean?) = (λ (x) #true)

procedure

(make-weak-custom-hash eql?    
  [hash1    
  hash2    
  #:key? key?])  dict?
  eql? : 
(or/c (any/c any/c . -> . any/c)
      (any/c any/c (any/c any/c . -> . any/c) . -> . any/c))
  hash1 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  hash2 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  key? : (any/c . -> . boolean?) = (λ (x) #true)

procedure

(make-immutable-custom-hash eql?    
  [hash1    
  hash2    
  #:key? key?])  dict?
  eql? : 
(or/c (any/c any/c . -> . any/c)
      (any/c any/c (any/c any/c . -> . any/c) . -> . any/c))
  hash1 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  hash2 : 
(or/c (any/c . -> . exact-integer?)
      (any/c (any/c . -> . exact-integer?) . -> . exact-integer?))
   = (const 1)
  key? : (any/c . -> . boolean?) = (λ (x) #true)
创建新字典类型的实例,基于 hash 表实现,其中键使用 eql? 比较,使用 hash1hash2 进行 hash,键谓词为 key?。参见 gen:equalgen:equal+hash 了解合适的相等和 hash 函数。

make-custom-hashmake-weak-custom-hash 函数创建不支持函数式更新的可变字典,而 make-immutable-custom-hash 创建支持函数式更新的不可变字典。make-weak-custom-hash 创建的字典弱引用其键,类似 make-weak-hash 的结果。

当具有相同的可变性和键引用强度、关联的过程是 equal? 的、且当键和值使用 equal? 比较时键值映射相同时,make-custom-hash 等创建的字典是 equal? 的。

另见 define-custom-hash-types

Examples:
> (define h (make-custom-hash (lambda (a b)
                                (string=? (format "~a" a)
                                          (format "~a" b)))
                              (lambda (a)
                                (equal-hash-code
                                 (format "~a" a)))))
> (dict-set! h 1 'one)
> (dict-ref h "1")

'one

4.18.6 Passing Keyword Arguments in Dictionaries🔗

procedure

(keyword-apply/dict proc    
  kw-dict    
  pos-arg ...    
  pos-args    
  #:<kw> kw-arg ...)  any
  proc : procedure?
  kw-dict : dict?
  pos-arg : any/c
  pos-args : (listof any/c)
  kw-arg : any/c
使用来自 (list* pos-arg ... pos-args) 的位置参数,以及来自 kw-dict 的关键字参数加上 #:<kw> kw-arg 序列中直接提供的关键字参数来应用 proc

kw-dict 中的所有键必须是关键字。kw-dict 中的关键字不必排序。但是,kw-dict 中的关键字与直接提供的 #:<kw> 关键字不得重叠。给定的 proc 必须接受 kw-dict 中的所有关键字加上 #:<kw>

Examples:
> (define (sundae #:ice-cream [ice-cream '("vanilla")]
                  #:toppings [toppings '("brownie-bits")]
                  #:sprinkles [sprinkles "chocolate"]
                  #:syrup [syrup "caramel"])
    (format "A sundae with ~a ice cream, ~a, ~a sprinkles, and ~a syrup."
            (string-join ice-cream #:before-last " and ")
            (string-join toppings #:before-last " and ")
            sprinkles
            syrup))
> (keyword-apply/dict sundae '((#:ice-cream    "chocolate"))  '())

"A sundae with chocolate ice cream, brownie-bits, chocolate sprinkles, and caramel syrup."

> (keyword-apply/dict sundae
                      (hash '#:toppings '("cookie-dough")
                            '#:sprinkles "rainbow"
                            '#:syrup "chocolate")
                      '())

"A sundae with vanilla ice cream, cookie-dough, rainbow sprinkles, and chocolate syrup."

> (keyword-apply/dict sundae
                      #:sprinkles "rainbow"
                      (hash '#:toppings '("cookie-dough")
                            '#:syrup "chocolate")
                      '())

"A sundae with vanilla ice cream, cookie-dough, rainbow sprinkles, and chocolate syrup."

Added in version 7.9 of package base.