hashtables.scm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. ;;; hashtables.scm --- The R6RS hashtables library
  2. ;; Copyright (C) 2010 Free Software Foundation, Inc.
  3. ;;
  4. ;; This library is free software; you can redistribute it and/or
  5. ;; modify it under the terms of the GNU Lesser General Public
  6. ;; License as published by the Free Software Foundation; either
  7. ;; version 3 of the License, or (at your option) any later version.
  8. ;;
  9. ;; This library is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Lesser General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Lesser General Public
  15. ;; License along with this library; if not, write to the Free Software
  16. ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. (library (rnrs hashtables (6))
  18. (export make-eq-hashtable
  19. make-eqv-hashtable
  20. make-hashtable
  21. hashtable?
  22. hashtable-size
  23. hashtable-ref
  24. hashtable-set!
  25. hashtable-delete!
  26. hashtable-contains?
  27. hashtable-update!
  28. hashtable-copy
  29. hashtable-clear!
  30. hashtable-keys
  31. hashtable-entries
  32. hashtable-equivalence-function
  33. hashtable-hash-function
  34. hashtable-mutable?
  35. equal-hash
  36. string-hash
  37. string-ci-hash
  38. symbol-hash)
  39. (import (rename (only (guile) string-hash-ci
  40. string-hash
  41. hashq
  42. hashv
  43. modulo
  44. *unspecified*
  45. @@)
  46. (string-hash-ci string-ci-hash))
  47. (only (ice-9 optargs) define*)
  48. (rename (only (srfi :69) make-hash-table
  49. hash
  50. hash-by-identity
  51. hash-table-size
  52. hash-table-ref/default
  53. hash-table-set!
  54. hash-table-delete!
  55. hash-table-exists?
  56. hash-table-update!/default
  57. hash-table-copy
  58. hash-table-equivalence-function
  59. hash-table-hash-function
  60. hash-table-keys
  61. hash-table-fold)
  62. (hash equal-hash)
  63. (hash-by-identity symbol-hash))
  64. (rnrs base (6))
  65. (rnrs records procedural (6)))
  66. (define r6rs:hashtable
  67. (make-record-type-descriptor
  68. 'r6rs:hashtable #f #f #t #t
  69. '#((mutable wrapped-table)
  70. (immutable orig-hash-function)
  71. (immutable mutable))))
  72. (define hashtable? (record-predicate r6rs:hashtable))
  73. (define make-r6rs-hashtable
  74. (record-constructor (make-record-constructor-descriptor
  75. r6rs:hashtable #f #f)))
  76. (define r6rs:hashtable-wrapped-table (record-accessor r6rs:hashtable 0))
  77. (define r6rs:hashtable-set-wrapped-table! (record-mutator r6rs:hashtable 0))
  78. (define r6rs:hashtable-orig-hash-function (record-accessor r6rs:hashtable 1))
  79. (define r6rs:hashtable-mutable? (record-accessor r6rs:hashtable 2))
  80. (define hashtable-mutable? r6rs:hashtable-mutable?)
  81. (define hash-by-value ((@@ (srfi srfi-69) caller-with-default-size) hashv))
  82. (define (wrap-hash-function proc)
  83. (lambda (key capacity) (modulo (proc key) capacity)))
  84. (define* (make-eq-hashtable #:optional k)
  85. (make-r6rs-hashtable
  86. (if k (make-hash-table eq? hashq k) (make-hash-table eq? symbol-hash))
  87. symbol-hash
  88. #t))
  89. (define* (make-eqv-hashtable #:optional k)
  90. (make-r6rs-hashtable
  91. (if k (make-hash-table eqv? hashv k) (make-hash-table eqv? hash-by-value))
  92. hash-by-value
  93. #t))
  94. (define* (make-hashtable hash-function equiv #:optional k)
  95. (let ((wrapped-hash-function (wrap-hash-function hash-function)))
  96. (make-r6rs-hashtable
  97. (if k
  98. (make-hash-table equiv wrapped-hash-function k)
  99. (make-hash-table equiv wrapped-hash-function))
  100. hash-function
  101. #t)))
  102. (define (hashtable-size hashtable)
  103. (hash-table-size (r6rs:hashtable-wrapped-table hashtable)))
  104. (define (hashtable-ref hashtable key default)
  105. (hash-table-ref/default
  106. (r6rs:hashtable-wrapped-table hashtable) key default))
  107. (define (hashtable-set! hashtable key obj)
  108. (if (r6rs:hashtable-mutable? hashtable)
  109. (hash-table-set! (r6rs:hashtable-wrapped-table hashtable) key obj))
  110. *unspecified*)
  111. (define (hashtable-delete! hashtable key)
  112. (if (r6rs:hashtable-mutable? hashtable)
  113. (hash-table-delete! (r6rs:hashtable-wrapped-table hashtable) key))
  114. *unspecified*)
  115. (define (hashtable-contains? hashtable key)
  116. (hash-table-exists? (r6rs:hashtable-wrapped-table hashtable) key))
  117. (define (hashtable-update! hashtable key proc default)
  118. (if (r6rs:hashtable-mutable? hashtable)
  119. (hash-table-update!/default
  120. (r6rs:hashtable-wrapped-table hashtable) key proc default))
  121. *unspecified*)
  122. (define* (hashtable-copy hashtable #:optional mutable)
  123. (make-r6rs-hashtable
  124. (hash-table-copy (r6rs:hashtable-wrapped-table hashtable))
  125. (r6rs:hashtable-orig-hash-function hashtable)
  126. (and mutable #t)))
  127. (define* (hashtable-clear! hashtable #:optional k)
  128. (if (r6rs:hashtable-mutable? hashtable)
  129. (let* ((ht (r6rs:hashtable-wrapped-table hashtable))
  130. (equiv (hash-table-equivalence-function ht))
  131. (hash-function (r6rs:hashtable-orig-hash-function hashtable))
  132. (wrapped-hash-function (wrap-hash-function hash-function)))
  133. (r6rs:hashtable-set-wrapped-table!
  134. hashtable
  135. (if k
  136. (make-hash-table equiv wrapped-hash-function k)
  137. (make-hash-table equiv wrapped-hash-function)))))
  138. *unspecified*)
  139. (define (hashtable-keys hashtable)
  140. (list->vector (hash-table-keys (r6rs:hashtable-wrapped-table hashtable))))
  141. (define (hashtable-entries hashtable)
  142. (let* ((ht (r6rs:hashtable-wrapped-table hashtable))
  143. (size (hash-table-size ht))
  144. (keys (make-vector size))
  145. (vals (make-vector size)))
  146. (hash-table-fold (r6rs:hashtable-wrapped-table hashtable)
  147. (lambda (k v i)
  148. (vector-set! keys i k)
  149. (vector-set! vals i v)
  150. (+ i 1))
  151. 0)
  152. (values keys vals)))
  153. (define (hashtable-equivalence-function hashtable)
  154. (hash-table-equivalence-function (r6rs:hashtable-wrapped-table hashtable)))
  155. (define (hashtable-hash-function hashtable)
  156. (r6rs:hashtable-orig-hash-function hashtable)))