Hi Thomas, it seems to me that you may have a misleading intuition for racket's hash tables. Racket has mutable and immutable hash tables these are implemented differently. Because as a user of hash tables you have to differentiate between mutable and immutable, there are also different hash operations some of which can only be used with mutable and other that are used with immutable hash tables.
Immutable hash tables are excellent for your use case, because you can easily keep around the original version just by keeping a variable/reference to it. As its name implies it is immutable/not changed, so when you "update" the hash that you are using as a set you aren't really updating it, instead you create a new updated hash from it, while the original version remains as it was. Because the immutable hash is implemented as a persistent data-structure with structural sharing, this is efficient, because it doesn't copy everything but instead only copies a few small internal nodes, those which need to be changed, the rest refers to the old/original version. Depending on the racket version there are different internal implementations of immutable hashes, but you can expect operations like hash-set to create a small extended version of your hash (if you are using racket's immutable hashes) that doesn't copy the complete hash. Immutable hash tables actually provide O(log N) access and update. Since N > is limited by the address space so that log N is limited to less than 30 > or 62 (depending on the platform), log N can be treated reasonably as a > constant. > from https://docs.racket-lang.org/reference/hashtables.html If you want to use the original hash as if it were a set you can do that by using hash operations instead of set operations like Stephen suggested. Another possibility is to create a custom-set implementation which wraps the hash to appear like a set, here is an example implementation: #lang racket (provide (contract-out [proxy-set (-> (and/c hash? immutable?) generic-set?)]) proxy-set->set proxy-set->seteq proxy-set->seteqv) (require racket/struct) (struct proxy-set [hash] ;; #:transparent #:methods gen:set [(define (set-member? s k) (hash-has-key? (proxy-set-hash s) k)) (define (set-add s v) (proxy-set (hash-set (proxy-set-hash s) v #f))) (define (set-remove s v) (proxy-set (hash-remove (proxy-set-hash s) v))) (define (set-empty? s) (hash-empty? (proxy-set-hash s))) (define (set-count s) (hash-count (proxy-set-hash s))) (define (set->stream s) (sequence->stream (in-immutable-hash-keys (proxy-set-hash s))))] #:methods gen:custom-write [(define write-proc (make-constructor-style-printer (lambda (s) 'proxy-set) (lambda (s) (in-immutable-hash-keys (proxy-set-hash s)))))]) ;; these functions are in case you eventually don't need the proxy anymore ;; and want to convert to a plain racket set (define/contract (proxy-set->set s) (-> proxy-set? (and/c generic-set? set-equal? set?)) (for/set ([k (in-immutable-hash-keys (proxy-set-hash s))]) k)) (define/contract (proxy-set->seteq s) (-> proxy-set? (and/c generic-set? set-eq? set?)) (for/seteq ([k (in-immutable-hash-keys (proxy-set-hash s))]) k)) (define/contract (proxy-set->seteqv s) (-> proxy-set? (and/c generic-set? set-eqv? set?)) (for/seteqv ([k (in-immutable-hash-keys (proxy-set-hash s))]) k)) (define-syntax-rule (show x) (displayln (format "~a: ~a" (quote x) x))) (define (example) (define original-map (hasheq 'a 4 'b 7 'c 1)) (show original-map) (define extended-map (hash-set original-map 'another 42)) (show extended-map) (define derived-set (proxy-set original-map)) (show derived-set) (define extended-set (set-union derived-set (seteq 'd 'e))) (show extended-set) (displayln "after all that the original map remains unchanged") (show original-map) (displayln "and the extended set does not modify the derived set") (show derived-set) (displayln "you also can merge the new keys from the extended-map") (displayln "with the extended-set at a later point") (define merged-set (set-union extended-set (proxy-set extended-map))) (show merged-set) (displayln "or convert the proxy-set to a plain racket set") (define plain-set (proxy-set->seteq merged-set)) (show plain-set)) (module+ main (example)) ;; output ;; original-map: #hasheq((a . 4) (b . 7) (c . 1)) ;; extended-map: #hasheq((a . 4) (another . 42) (b . 7) (c . 1)) ;; derived-set: #<proxy-set: a c b> ;; extended-set: #<proxy-set: a e d c b> ;; after all that the original map remains unchanged ;; original-map: #hasheq((a . 4) (b . 7) (c . 1)) ;; and the extended set does not modify the derived set ;; derived-set: #<proxy-set: a c b> ;; you also can merge the new keys from the extended-map ;; with the extended-set at a later point ;; merged-set: #<proxy-set: a e another d c b> ;; or convert the proxy-set to a plain racket set ;; plain-set: #<seteq: a e another d c b> -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/f28d4b23-7544-4698-a9b3-b004b989f0c9%40googlegroups.com.