Racket 可变哈希到不可变哈希

问题描述 投票:0回答:2

我正在使用过程

hash-set
hash?
中设置值。似乎要求哈希值是
immutable?
。到目前为止,我找不到比以下更好的方法将可变哈希转换为不可变哈希:

(make-immutable-hash(哈希->列出 myhash))

哈希值是一些

yaml
,我正在从文件中读取它,并且
yaml
模块为我提供了一个可变哈希值。例如我有以下代码:

(hash-set yaml-hash
                "content"
                (make-immutable-hash
                 (hash->list
                  (my-hash-map content-hash
                               (lambda (key value)
                                 (cons key
                                       (markdown-to-html value)))))))

是否有更好的方法将可变哈希转换为不可变哈希,以便更新它?还是我应该走不同的路?

hashmap hashtable racket immutability
2个回答
2
投票

如果哈希值一开始就是可变的,你可以直接使用

hash-set!
:

修改它
(hash-set! yaml-hash <key> <new-value>)

上面的内容将就地更改哈希值,而

hash-set
将返回一个new哈希值,您必须将其存储或重新分配到其他地方。


2
投票

我找不到比以下更好的方法将可变哈希转换为不可变哈希:

(make-immutable-hash (hash->list myhash))

您可以使用

for/hash
理解
in-hash
序列
一次迭代一个可变哈希的条目,而不是首先构建所有条目的列表:

;;; Contract: (-> hash? (and/c hash? immutable?))
(define (hash->immutable-hash table)
  (if (immutable? table) 
      table ;; If hash is already immutable, just return it
      (for/hash ([(k v) (in-mutable-hash my-table)]) (values k v))))

Racket 8.6 在我最初发布此答案后不久发布,添加了一个

hash-map/copy
函数,该函数也可用于制作可变哈希的不可变副本。与上面不同的是,它保留了表的相等函数(
eq?
eqv?
equal?
equal-always?
)。

使用它的上述版本,这是现在我的首选方法:

;;; Contract: (-> hash?  (and/c hash? immutable?))
(define (hash->immutable-hash table)
  (if (immutable? table) 
      table ;; If hash is already immutable, just return it
      (hash-map/copy table values #:kind 'immutable)))
© www.soinside.com 2019 - 2024. All rights reserved.