Skip to content

Instantly share code, notes, and snippets.

@tonyg
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonyg/86d0052c9c28431e1546 to your computer and use it in GitHub Desktop.
Save tonyg/86d0052c9c28431e1546 to your computer and use it in GitHub Desktop.
Hash consing in Racket. (eq => equal) by definition; this makes (equal => eq).
#lang racket/base
(provide canonicalize)
(require ffi/unsafe/atomic)
(define canonical-values (make-weak-hash))
(define (canonicalize val)
(start-atomic)
(define b (hash-ref canonical-values
val
(lambda ()
(hash-set! canonical-values val (make-weak-box val))
#f)))
(end-atomic)
(if b (weak-box-value b) val))
(module+ test
(require rackunit)
(define v1 (canonicalize (cons 1 2)))
(let ((v2 (canonicalize (cons 1 2))))
(check-eq? v1 v2))
(collect-garbage)
(check-equal? (hash-count canonical-values) 1)
(let ((v2 (canonicalize (cons 1 2))))
(check-eq? v1 v2))
(set! v1 (canonicalize (cons 1 2)))
(collect-garbage)
(check-equal? (hash-count canonical-values) 1)
(let ((v2 (canonicalize (cons 1 2))))
(check-eq? v1 v2))
(set! v1 #f)
(collect-garbage)
(check-equal? (hash-count canonical-values) 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment