Skip to content

Commit 80dc1ff

Browse files
authored
Implement hash set in terms of hash map (#114)
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 00bf7d8 commit 80dc1ff

3 files changed

Lines changed: 43 additions & 52 deletions

File tree

pkg/lang/set.go

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,39 @@ type Set struct {
99
meta IPersistentMap
1010
hash, hasheq uint32
1111

12-
vals []interface{}
12+
hashMap IPersistentMap
1313
}
1414

15-
type PersistentHashSet = Set // hack until we have a proper persistent hash set
15+
type PersistentHashSet = Set
1616

17-
func CreatePersistentTreeSet(keys ISeq) interface{} {
17+
func CreatePersistentTreeSet(keys ISeq) any {
1818
// TODO: implement
1919
return NewSet(seqToSlice(keys)...)
2020
}
2121

22-
func CreatePersistentTreeSetWithComparator(comparator IFn, keys ISeq) interface{} {
22+
func CreatePersistentTreeSetWithComparator(comparator IFn, keys ISeq) any {
2323
// TODO: implement
2424
return NewSet(seqToSlice(keys)...)
2525
}
2626

27-
func NewSet(vals ...interface{}) *Set {
27+
func NewSet(vals ...any) *Set {
2828
set, err := NewSet2(vals...)
2929
if err != nil {
3030
panic(err)
3131
}
3232
return set
3333
}
3434

35-
func NewSet2(vals ...interface{}) (*Set, error) {
36-
// check for duplicates
35+
func NewSet2(vals ...any) (*Set, error) {
36+
set := &Set{
37+
hashMap: NewPersistentHashMap(),
38+
}
3739
for i := 0; i < len(vals); i++ {
38-
for j := i + 1; j < len(vals); j++ {
39-
if Equiv(vals[i], vals[j]) {
40-
return nil, NewIllegalArgumentError(fmt.Sprintf("duplicate key: %v", vals[i]))
41-
}
42-
}
40+
val := vals[i]
41+
set.hashMap = set.hashMap.Assoc(val, true).(IPersistentMap)
4342
}
4443

45-
return &Set{
46-
vals: vals,
47-
}, nil
44+
return set, nil
4845
}
4946

5047
var (
@@ -55,57 +52,52 @@ var (
5552
emptySet = NewSet()
5653
)
5754

58-
func (s *Set) Get(key interface{}) interface{} {
59-
for _, v := range s.vals {
60-
if Equiv(v, key) {
61-
return v
62-
}
55+
func (s *Set) Get(key any) any {
56+
val := s.hashMap.ValAt(key)
57+
if val == true {
58+
return key
6359
}
6460
return nil
6561
}
6662

67-
func (s *Set) Invoke(args ...interface{}) interface{} {
63+
func (s *Set) Invoke(args ...any) any {
6864
if len(args) != 1 {
6965
panic(fmt.Errorf("set apply expects 1 argument, got %d", len(args)))
7066
}
7167

7268
return s.Get(args[0])
7369
}
7470

75-
func (s *Set) ApplyTo(args ISeq) interface{} {
71+
func (s *Set) ApplyTo(args ISeq) any {
7672
return s.Invoke(seqToSlice(args)...)
7773
}
7874

79-
func (s *Set) Cons(v interface{}) Conser {
75+
func (s *Set) Cons(v any) Conser {
8076
if s.Contains(v) {
8177
return s
8278
}
83-
return NewSet(append(s.vals, v)...)
79+
return &Set{
80+
meta: s.meta,
81+
hashMap: s.hashMap.Assoc(v, true).(IPersistentMap),
82+
}
8483
}
8584

86-
func (s *Set) Disjoin(v interface{}) IPersistentSet {
87-
for i, val := range s.vals {
88-
if Equiv(val, v) {
89-
newItems := make([]interface{}, len(s.vals)-1)
90-
copy(newItems, s.vals[:i])
91-
copy(newItems[i:], s.vals[i+1:])
92-
return NewSet(newItems...)
93-
}
85+
func (s *Set) Disjoin(v any) IPersistentSet {
86+
if !s.Contains(v) {
87+
return s
88+
}
89+
return &Set{
90+
meta: s.meta,
91+
hashMap: s.hashMap.Without(v).(IPersistentMap),
9492
}
95-
return s
9693
}
9794

98-
func (s *Set) Contains(v interface{}) bool {
99-
for _, val := range s.vals {
100-
if Equiv(val, v) {
101-
return true
102-
}
103-
}
104-
return false
95+
func (s *Set) Contains(v any) bool {
96+
return s.hashMap.ContainsKey(v)
10597
}
10698

10799
func (s *Set) Count() int {
108-
return len(s.vals)
100+
return s.hashMap.Count()
109101
}
110102

111103
func (s *Set) xxx_counted() {}
@@ -122,7 +114,7 @@ func (s *Set) String() string {
122114
return PrintString(s)
123115
}
124116

125-
func (s *Set) Equals(v2 interface{}) bool {
117+
func (s *Set) Equals(v2 any) bool {
126118
if s == v2 {
127119
return true
128120
}
@@ -143,10 +135,10 @@ func (s *Set) Equals(v2 interface{}) bool {
143135
}
144136

145137
func (s *Set) Seq() ISeq {
146-
if s.Count() == 0 {
138+
if s.hashMap.Count() == 0 {
147139
return nil
148140
}
149-
return NewSliceSeq(s.vals)
141+
return NewMapKeySeq(Seq(s.hashMap))
150142
}
151143

152144
func (s *Set) Equiv(o any) bool {
@@ -165,15 +157,14 @@ func (s *Set) Meta() IPersistentMap {
165157
return s.meta
166158
}
167159

168-
func (s *Set) WithMeta(meta IPersistentMap) interface{} {
160+
func (s *Set) WithMeta(meta IPersistentMap) any {
169161
if meta == s.meta {
170162
return s
171163
}
172164

173-
return &Set{
174-
meta: meta,
175-
vals: s.vals,
176-
}
165+
cpy := *s
166+
cpy.meta = meta
167+
return &cpy
177168
}
178169

179170
func (s *Set) AsTransient() ITransientCollection {
@@ -185,7 +176,7 @@ type TransientSet struct {
185176
*Set
186177
}
187178

188-
func (s *TransientSet) Conj(v interface{}) Conjer {
179+
func (s *TransientSet) Conj(v any) Conjer {
189180
return &TransientSet{Set: s.Set.Cons(v).(*Set)}
190181
}
191182

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
#{:a :b :c}
1+
#{:a}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
#{:a :b :c}
1+
#{:a}

0 commit comments

Comments
 (0)