Last active
August 29, 2015 14:03
-
-
Save tonyg/86d0052c9c28431e1546 to your computer and use it in GitHub Desktop.
Hash consing in Racket. (eq => equal) by definition; this makes (equal => eq).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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