hashtable.scm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. ;;; Hash a string.
  2. (define (hash-string str size)
  3. (let ((len (string-length str)))
  4. (let loop ((i 0)
  5. (accum 0))
  6. (if (= i len)
  7. (modulo accum size)
  8. (loop (+ i 1)
  9. (modulo
  10. (+ (builtin char->integer (string-ref str i))
  11. (* 31 accum))
  12. size))))))
  13. ;;; Hash an object.
  14. (define (hash obj size)
  15. (cond ((number? obj) (modulo obj size))
  16. ((string? obj) (hash-string obj size))
  17. ((symbol? obj)
  18. (hash-string (symbol->string obj) size))
  19. ((char? obj)
  20. (hash-string (make-string 1 obj) size))
  21. ((boolean? obj)
  22. (modulo (if obj 2 1) size))
  23. ((pair? obj)
  24. (modulo
  25. (+ (hash (car obj) size)
  26. (hash (cdr obj) size))
  27. size))
  28. (else 0)))
  29. ;;; Hash table type tag.
  30. (define hash-table-tag (list 'hash-table))
  31. (define (tagged-vector? obj tag)
  32. (and (vector? obj)
  33. (> (vector-length obj) 0)
  34. (eq? (vector-ref obj 0) tag)))
  35. ;;; Return #t if obj is a hash table.
  36. (define (hash-table? obj)
  37. (tagged-vector? obj hash-table-tag))
  38. (define (make-hash-table-aux aproc)
  39. (lambda ()
  40. (let ((size 101))
  41. (vector hash-table-tag aproc
  42. (make-vector size '())))))
  43. ;;; Make a hash table using assoc.
  44. (define make-hash-table (make-hash-table-aux assoc))
  45. ;;; Make a hash table using assq.
  46. ;;; Get the associative list procedure
  47. ;;; from a hash table.
  48. (define (hash-table-aproc ht) (vector-ref ht 1))
  49. ;;; Get the vector from a hash table.
  50. (define (hash-table-vector ht) (vector-ref ht 2))
  51. (define (hash-table-using aproc)
  52. (lambda (obj)
  53. (and (hash-table? obj)
  54. (eq? (hash-table-aproc obj) aproc))))
  55. ;;; Set a value in a hash table.
  56. (define (hash-table-set! ht key val)
  57. (let ((vec (hash-table-vector ht)))
  58. (let ((hashval (hash key (vector-length vec))))
  59. (let ((alist (vector-ref vec hashval)))
  60. (let ((pair ((hash-table-aproc ht) key alist)))
  61. (if pair
  62. (set-cdr! pair val)
  63. (vector-set! vec hashval
  64. (cons (cons key val)
  65. alist))))))))
  66. ;;; Get a value from a hash table.
  67. (define (hash-table-ref ht key default)
  68. (let ((vec (hash-table-vector ht)))
  69. (let ((res ((hash-table-aproc ht)
  70. key
  71. (vector-ref vec (hash key (vector-length vec))))))
  72. (if res (cdr res) default))))
  73. (define (hash-table-pred ht)
  74. equal?)
  75. ;(let ((aproc (hash-table-aproc ht)))
  76. ;(cond ((eq? aproc assq) eq?)
  77. ; ((eq? aproc assv) eqv?)
  78. ; ((eq? aproc assoc) equal?))))
  79. ;;; Delete a key from a hash table.
  80. (define (hash-table-delete! ht key)
  81. (let ((pred? (hash-table-pred ht))
  82. (vec (hash-table-vector ht)))
  83. (let ((hashval (hash key (vector-length vec))))
  84. (let loop ((alist (vector-ref vec hashval))
  85. (accum '()))
  86. (cond ((null? alist)
  87. (vector-set! vec hashval accum))
  88. ((pred? (caar alist) key)
  89. (loop (cdr alist) accum))
  90. (else
  91. (loop (cdr alist)
  92. (cons (car alist) accum))))))))
  93. ;;; Convert an associative list to
  94. ;;; a hash table.
  95. (define (alist->hash-table-aux aproc)
  96. (lambda (alist)
  97. (let ((ht ((make-hash-table-aux aproc))))
  98. (for-each
  99. (lambda (pair)
  100. (hash-table-set! ht (car pair) (cdr pair)))
  101. alist)
  102. ht)))
  103. (define alist->hash-table (alist->hash-table-aux assoc))
  104. ;(define alist->hash-tableq (alist->hash-table-aux assq))
  105. ;(define alist->hash-tablev (alist->hash-table-aux assv))
  106. (define (every n lst)
  107. (cond ((null? lst) '())
  108. ((zero? n) (every (+ n 1) (cdr lst)))
  109. (else
  110. (cons (car lst)
  111. (every (- n 1) (cdr lst))))))
  112. (define (zip a b)
  113. (map cons a b))
  114. ;(define (hash-table . args)
  115. ; (alist->hash-table
  116. ; (zip (every 1 args) (every 0 args))))
  117. ;(define (hash-tableq . args)
  118. ; (alist->hash-tableq
  119. ; (zip (every 1 args) (every 0 args))))
  120. ;(define (hash-tablev . args)
  121. ; (alist->hash-tablev
  122. ; (zip (every 1 args) (every 0 args))))
  123. ;;; Convert a hash table to an
  124. ;;; associative list.
  125. (define (concatenate lol)
  126. (if (null? lol)
  127. '()
  128. (append (car lol) (concatenate (cdr lol)))))
  129. (define (hash-table->alist ht)
  130. (concatenate
  131. (vector->list (hash-table-vector ht))))
  132. ;;; Make a copy of an associative list.
  133. ;;; The new one is backwards, but that should
  134. ;;; not matter.
  135. (define (alist-copy alist)
  136. (let loop ((alist alist)
  137. (accum '()))
  138. (if (null? alist)
  139. accum
  140. (loop
  141. (cdr alist)
  142. (cons (cons (caar alist) (cdar alist)) accum)))))
  143. ;;; Make a copy of a hash table.
  144. (define (hash-table-copy ht)
  145. (let ((old-vec (hash-table-vector ht)))
  146. (let ((size (vector-length old-vec)))
  147. (let ((new-vec (make-vector size)))
  148. (let loop ((i 0))
  149. (if (= i size)
  150. (vector hash-table-tag (hash-table-aproc ht) new-vec)
  151. (begin
  152. (vector-set! new-vec i
  153. (alist-copy (vector-ref old-vec i)))
  154. (loop (+ i 1)))))))))