syndicate-rkt/syndicate/support/hash.rkt

45 lines
1.4 KiB
Racket

;;; SPDX-License-Identifier: LGPL-3.0-or-later
;;; SPDX-FileCopyrightText: Copyright © 2010-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
#lang racket/base
;; Hash-table utilities that are not (yet) part of Racket
(provide hash-set/remove
hashset-member?
hashset-add
hashset-remove
in-hashset-values)
(require (only-in racket/set set seteq seteqv))
(define (hash-set/remove ht key val [default-val #f] #:compare [compare equal?])
(if (compare val default-val)
(hash-remove ht key)
(hash-set ht key val)))
(define (hashset-member? ht key val)
(define s (hash-ref ht key #f))
(and s (hash-has-key? s val)))
(define (make-hash-from-set-ctor ctor)
(cond [(eq? ctor set) (hash)]
[(eq? ctor seteq) (hasheq)]
[(eq? ctor seteqv) (hasheqv)]
[else (error 'hash-ctor-for-set-ctor "Cannot use hashset with set constructor ~v" ctor)]))
(define (hashset-add ht key val #:set [set-ctor set])
(define old-set (hash-ref ht key (lambda () (make-hash-from-set-ctor set-ctor))))
(hash-set ht key (hash-set old-set val #t)))
(define (hashset-remove ht k v)
(define old (hash-ref ht k #f))
(if old
(let ((new (hash-remove old v)))
(if (hash-empty? new)
(hash-remove ht k)
(hash-set ht k new)))
ht))
(define-syntax-rule (in-hashset-values ht key)
(in-hash-keys (hash-ref ht key hash)))