set.lisp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. "This module implements hash sets as backed by hash maps, optionally
  2. with a custom hash function."
  3. (import data/struct ())
  4. (defstruct (set make-set set?)
  5. "Create a new, empty set with the given HASH-FUNCTION. If no
  6. hash function is given, [[make-set]] defaults to using object
  7. identity, that is, [[id]].
  8. **Note**: Comparison for sets also compares their hash function
  9. with pointer equality, meaning that sets will only compare equal
  10. if their hash function is _the same object_.
  11. ### Example
  12. ```
  13. > (make-set id)
  14. out = «hash-set: »
  15. ```"
  16. (fields
  17. (immutable hash-function (hide hashset-fn))
  18. (immutable data (hide hashset-data)))
  19. (constructor new
  20. (lambda ((hash id))
  21. (new hash {}))))
  22. (defmethod (eq? set set) (x y)
  23. (let* [(same-data true)]
  24. (for-pairs (k _) (hashset-data y)
  25. (when (= (.> (hashset-data x) k) nil)
  26. (set! same-data false)))
  27. (and (= (hashset-fn x)
  28. (hashset-fn y))
  29. same-data)))
  30. (defun element? (set val)
  31. "Check if VAL is an element of SET.
  32. ### Example:
  33. ```cl
  34. > (element? (set-of 1 2 3) 1)
  35. out = true
  36. ```"
  37. (assert-type! set set)
  38. (let* [(hash (hashset-fn set))]
  39. (/= (.> (hashset-data set) (hash val)) nil)))
  40. (defun insert! (set &vals)
  41. "Insert VALS into SET.
  42. ### Example
  43. ```cl
  44. > (define set (set-of 1 2 3))
  45. out = «hash-set: 1 2 3»
  46. > (insert! set 4)
  47. out = «hash-set: 1 2 3 4»
  48. > set
  49. out = «hash-set: 1 2 3 4»
  50. ```"
  51. (assert-type! set set)
  52. (let* [(hash (hashset-fn set))]
  53. (map (lambda (v)
  54. (.<! (hashset-data set) (hash v) v))
  55. vals))
  56. set)
  57. (defun insert (set &vals)
  58. "Build a copy of SET with VALs inserted.
  59. ### Example
  60. ```cl
  61. > (insert (set-of 1 2 3) 4 5 6)
  62. out = «hash-set: 1 2 3 4 5 6»
  63. ```"
  64. (assert-type! set set)
  65. (let* [(hash (hashset-fn set))
  66. (out (make-set hash))]
  67. (for-pairs (k v) (hashset-data set)
  68. (.<! (hashset-data out) k v))
  69. (for-each v vals
  70. (.<! (hashset-data out) (hash v) v))
  71. out))
  72. (defun union (&sets)
  73. "The set of values that occur in any set in the SETS.
  74. ### Example:
  75. ```cl
  76. > (union (set-of 1 2 3) (set-of 4 5 6))
  77. out = «hash-set: 1 2 3 4 5 6»
  78. > (union (set-of 1 2) (set-of 2 3) (set-of 3 4))
  79. out = «hash-set: 1 2 3 4»
  80. ```"
  81. (when (empty? sets)
  82. (format 1 "(union): can't take the union of no sets"))
  83. (let* [(out (make-set (hashset-fn (car sets))))
  84. (fn (hashset-fn (car sets)))]
  85. (do [(set sets)]
  86. (assert-type! set set)
  87. (unless (= (hashset-fn set) fn)
  88. (format 1 "(union {@( )}): set '{}' does not have same hash function as the other sets" sets set))
  89. (for-pairs (k v) (hashset-data set)
  90. (insert! out v)))
  91. out))
  92. (defun intersection (&sets)
  93. "The set of values that occur in all the SETS.
  94. ### Example:
  95. ```cl
  96. > (intersection (set-of 1 2 3) (set-of 3 4 5))
  97. out = «hash-set: 3»
  98. > (intersection (set-of 1 2 3) (set-of 3 4 5) (set-of 7 8 9))
  99. out = «hash-set: »
  100. ```"
  101. (letrec [(pairwise-intersection (lambda (a b)
  102. (assert-type! a set)
  103. (assert-type! b set)
  104. (unless (= (hashset-fn a) (hashset-fn b))
  105. (format 1 "(intersection {}): {#a} and {#b} do not have the same hash function." sets))
  106. (let* [(out (make-set (hashset-fn a)))]
  107. (for-pairs (k v) (hashset-data a)
  108. (when (.> (hashset-data b) k)
  109. (.<! (hashset-data out) k v)))
  110. out)))
  111. (inter (lambda (&sets)
  112. (case sets
  113. [(?x) x]
  114. [(?x ?y) (pairwise-intersection x y)]
  115. [(?x ?y . ?xs) (apply inter (pairwise-intersection x y) xs)])))]
  116. (map (lambda (x)
  117. (unless (set? x)
  118. (format 1 "(intersection {}): '{}' is not a set" sets x)))
  119. sets)
  120. (apply inter sets)))
  121. (defun cardinality (set)
  122. "Return the number of elements in SET.
  123. ### Example:
  124. ```cl
  125. > (cardinality (set-of 1 2 3))
  126. out = 3
  127. > (cardinality (set-of 1 1 2))
  128. out = 2
  129. ```"
  130. (let* [(out 0)]
  131. (for-pairs (_ _) (hashset-data set)
  132. (inc! out))
  133. out))
  134. (defun disjoint? (&sets)
  135. "Is the intersection of SETS empty?
  136. ### Example:
  137. ```cl
  138. > (disjoint? (set-of 1 2 3) (set-of 3 4 5))
  139. out = false
  140. > (disjoint? (set-of 1 2 3) (set-of 4 5 6))
  141. out = true
  142. ```"
  143. (= (cardinality (apply intersection sets)) 0))
  144. (defun set-of (&values)
  145. "Create the set containing VALUES with the default hash function.
  146. ### Example:
  147. ```cl
  148. > (set-of 1 2 3)
  149. out = «hash-set: 1 2 3»
  150. ```"
  151. (let* [(out (make-set))]
  152. (map (cut insert! out <>) values)
  153. out))
  154. (defun set->list (set)
  155. "Convert SET to a list. Note that, since hash sets have no specified
  156. order, the list will not nescessarily be sorted."
  157. (assert-type! set set)
  158. (let* [(out '())]
  159. (for-pairs (_ v) (hashset-data set)
  160. (push! out v))
  161. out))
  162. (defmethod (pretty set) (x)
  163. (.. "«hash-set: " (concat (map pretty (set->list x)) " ") "»"))