-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e5ceca1
commit 4537477
Showing
15 changed files
with
1,586 additions
and
1,574 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,113 @@ | ||
(require-builtin #%private/steel/mhash as private.) | ||
(provide (contract/out mhash-set! (->/c mhash? any/c any/c any/c)) | ||
(contract/out mhash-ref (->/c mhash? any/c any/c)) | ||
mhash | ||
(contract/out mhash->hash (->/c mhash? hash?)) | ||
(contract/out mhash-length (->/c mhash? int?)) | ||
(contract/out mhash-contains? (->/c mhash? bool?)) | ||
(contract/out mhash-keys->list (->/c mhash? list?)) | ||
(contract/out mhash-values->list (->/c mhash? list?)) | ||
(contract/out mhash->list (->/c mhash? list?)) | ||
(contract/out mhash? (->/c any/c bool?)) | ||
no-contract-mhash-ref) | ||
|
||
(struct mutable-hash (inner) #:mutable) | ||
(define (for-each func lst) | ||
(if (null? lst) | ||
void | ||
(begin | ||
(func (car lst)) | ||
(when (null? lst) | ||
(return! void)) | ||
(for-each func (cdr lst))))) | ||
|
||
;; Manually box the hash map | ||
(struct mutable-hash (inner) | ||
#:printer | ||
(lambda (obj printer) | ||
(simple-display "'#mhash(") | ||
(let ([hash-as-list-of-pairs (transduce (#%unbox (mutable-hash-inner obj)) (into-list))]) | ||
(cond | ||
[(empty? hash-as-list-of-pairs) (simple-display ")")] | ||
[else | ||
|
||
(simple-display "(") | ||
(printer (caar hash-as-list-of-pairs)) | ||
(simple-display " . ") | ||
(printer (cadar hash-as-list-of-pairs)) | ||
(simple-display ")") | ||
|
||
(for-each (λ (obj) | ||
(simple-display " (") | ||
(printer (car obj)) | ||
(simple-display " . ") | ||
(printer (list-ref obj 1)) | ||
(simple-display ")")) | ||
(cdr hash-as-list-of-pairs)) | ||
|
||
(simple-display ")")])))) | ||
|
||
(define mhash? mutable-hash?) | ||
|
||
;;@doc | ||
;; Mutably update the hashmap in place, setting the key and value accordingly. | ||
(define (mhash-set! mhash key value) | ||
(private.mhash-set! (mutable-hash-inner mhash) key value)) | ||
(swap-with-expr (mutable-hash-inner mhash) (lambda (h) (hash-insert h key value)))) | ||
|
||
;;@doc | ||
;; Fetch the value for the given key | ||
(define (mhash-ref mhash key) | ||
(private.mhash-ref (mutable-hash-inner mhash) key)) | ||
(hash-ref (#%unbox (mutable-hash-inner mhash)) key)) | ||
|
||
(define no-contract-mhash-ref mhash-ref) | ||
|
||
;;@doc | ||
;; Construct a mutable hash map from the given key value pairs | ||
(define (mhash . args) | ||
(mutable-hash (#%box (apply hash args)))) | ||
|
||
;;@doc | ||
;; If you want to call any methods that | ||
;; exist for an immutable hash, just delegate here. | ||
;; | ||
;; This conversion is very inexpensive, and does not copy | ||
;; the entire vector. | ||
(define (mhash->hash mh) | ||
(#%unbox (mutable-hash-inner mh))) | ||
|
||
;;@doc | ||
;; Get the length of the mutable hash table. The length is defined | ||
;; as the number of key value pairs. | ||
(define (mhash-length mh) | ||
(hash-length (mhash->hash mh))) | ||
|
||
(define (mhash) | ||
(mutable-hash (private.mhash))) | ||
;;@doc | ||
;; Check if this mutable hash contains a key | ||
(define (mhash-contains? mh key) | ||
(hash-contains? (mhash->hash mh) key)) | ||
|
||
(define (loop) | ||
(define my-hash (mhash)) | ||
;;@doc | ||
;; Get the keys of this mutable hash map as a list | ||
(define (mhash-keys->list mh) | ||
(hash-keys->list (mhash->hash mh))) | ||
|
||
(mhash-set! my-hash 'foo 'bar) | ||
(mhash-set! my-hash 'bar 'foo) | ||
;;@doc | ||
;; Get the values of this mutable hash map as a list | ||
(define (mhash-values->list mh) | ||
(hash-values->list (mhash->hash mh))) | ||
|
||
(mhash-set! my-hash 'baz my-hash) | ||
;;@doc | ||
;; Convert this mutable hash into an association list, which | ||
;; in this case is a list of pairs. | ||
(define (mhash->list mh) | ||
(transduce (mhash->hash mh) (into-list))) | ||
|
||
(loop)) | ||
;; Swap the contents of the boxed value | ||
;; in place, so that we can perform in place | ||
;; updates where relevant. | ||
;; | ||
;; Note: This might actually just be slower, but | ||
;; for the sake of experimenting we'll go with it. | ||
(define (swap-with-expr boxed-value thunk) | ||
;; Replace the inner box with void | ||
(let ([previous (#%set-box! boxed-value void)]) | ||
(with-handler (lambda (err) (#%set-box! boxed-value previous)) | ||
(#%set-box! boxed-value (thunk previous))))) |
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
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
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
Oops, something went wrong.