From a74b83e3f275e44f686066081c7fdb665180ff9e Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Thu, 12 Jan 2023 10:22:46 +0100 Subject: [PATCH] sets & maps: remove varargs APIs & SetMany variants The implementation behind the API is not more efficient than manually looping over a data structure and inserting elements one-by-one. --- immutable.go | 19 ------------------- sets.go | 48 ++++++++++++++++-------------------------------- sets_test.go | 10 +++++----- 3 files changed, 21 insertions(+), 56 deletions(-) diff --git a/immutable.go b/immutable.go index 4a42e33..e43bc70 100644 --- a/immutable.go +++ b/immutable.go @@ -752,17 +752,6 @@ func (m *Map[K, V]) Set(key K, value V) *Map[K, V] { return m.set(key, value, false) } -// SetMany returns a map with the keys set to the new values. nil values are allowed. -// -// This function will return a new map even if the updated value is the same as -// the existing value because Map does not track value equality. -func (m *Map[K, V]) SetMany(entries map[K]V) *Map[K, V] { - for k, v := range entries { - m = m.Set(k, v) - } - return m -} - func (m *Map[K, V]) set(key K, value V, mutable bool) *Map[K, V] { // Set a hasher on the first value if one does not already exist. hasher := m.hasher @@ -1641,14 +1630,6 @@ func (m *SortedMap[K, V]) Set(key K, value V) *SortedMap[K, V] { return m.set(key, value, false) } -// SetMany returns a map with the keys set to the new values. -func (m *SortedMap[K, V]) SetMany(entries map[K]V) *SortedMap[K, V] { - for k, v := range entries { - m = m.Set(k, v) - } - return m -} - func (m *SortedMap[K, V]) set(key K, value V, mutable bool) *SortedMap[K, V] { // Set a comparer on the first value if one does not already exist. comparer := m.comparer diff --git a/sets.go b/sets.go index 28f888d..d610c15 100644 --- a/sets.go +++ b/sets.go @@ -14,31 +14,23 @@ type Set[T comparable] struct { // Default hasher implementations only exist for int, string, and byte slice types. // NewSet can also take some initial values as varargs. func NewSet[T comparable](hasher Hasher[T], values ...T) Set[T] { - s := Set[T]{ - m: NewMap[T, struct{}](hasher), - } + m := NewMap[T, struct{}](hasher) for _, value := range values { - s.m = s.m.set(value, struct{}{}, true) + m = m.set(value, struct{}{}, true) } - return s + return Set[T]{m} } -// Set returns a set containing the new value. +// Add returns a set containing the new value. // // This function will return a new set even if the set already contains the value. -func (s Set[T]) Set(values ...T) Set[T] { - for _, value := range values { - s.m = s.m.Set(value, struct{}{}) - } - return s +func (s Set[T]) Add(value T) Set[T] { + return Set[T]{s.m.Set(value, struct{}{})} } // Delete returns a set with the given key removed. -func (s Set[T]) Delete(values ...T) Set[T] { - for _, value := range values { - s.m = s.m.Delete(value) - } - return s +func (s Set[T]) Delete(value T) Set[T] { + return Set[T]{s.m.Delete(value)} } // Has returns true when the set contains the given value @@ -127,31 +119,23 @@ type SortedSet[T comparable] struct { // exist for int, string, and byte slice keys. // NewSortedSet can also take some initial values as varargs. func NewSortedSet[T comparable](comparer Comparer[T], values ...T) SortedSet[T] { - s := SortedSet[T]{ - m: NewSortedMap[T, struct{}](comparer), - } + m := NewSortedMap[T, struct{}](comparer) for _, value := range values { - s.m = s.m.set(value, struct{}{}, true) + m = m.set(value, struct{}{}, true) } - return s + return SortedSet[T]{m} } -// Set returns a set containing the new value. +// Add returns a set containing the new value. // // This function will return a new set even if the set already contains the value. -func (s SortedSet[T]) Set(values ...T) SortedSet[T] { - for _, value := range values { - s.m = s.m.Set(value, struct{}{}) - } - return s +func (s SortedSet[T]) Add(value T) SortedSet[T] { + return SortedSet[T]{s.m.Set(value, struct{}{})} } // Delete returns a set with the given key removed. -func (s SortedSet[T]) Delete(values ...T) SortedSet[T] { - for _, value := range values { - s.m = s.m.Delete(value) - } - return s +func (s SortedSet[T]) Delete(value T) SortedSet[T] { + return SortedSet[T]{s.m.Delete(value)} } // Has returns true when the set contains the given value diff --git a/sets_test.go b/sets_test.go index 5a83eb9..ca3aa3d 100644 --- a/sets_test.go +++ b/sets_test.go @@ -6,8 +6,8 @@ import ( func TestSetsPut(t *testing.T) { s := NewSet[string](nil) - s2 := s.Set("1").Set("1") - s2.Set("2") + s2 := s.Add("1").Add("1") + s2.Add("2") if s.Len() != 0 { t.Fatalf("Unexpected mutation of set") } @@ -34,7 +34,7 @@ func TestSetsPut(t *testing.T) { func TestSetsDelete(t *testing.T) { s := NewSet[string](nil) - s2 := s.Set("1") + s2 := s.Add("1") s3 := s.Delete("1") if s2.Len() != 1 { t.Fatalf("Unexpected non-mutation of set") @@ -52,7 +52,7 @@ func TestSetsDelete(t *testing.T) { func TestSortedSetsPut(t *testing.T) { s := NewSortedSet[string](nil) - s2 := s.Set("1").Set("1").Set("0") + s2 := s.Add("1").Add("1").Add("0") if s.Len() != 0 { t.Fatalf("Unexpected mutation of set") } @@ -86,7 +86,7 @@ func TestSortedSetsPut(t *testing.T) { func TestSortedSetsDelete(t *testing.T) { s := NewSortedSet[string](nil) - s2 := s.Set("1") + s2 := s.Add("1") s3 := s.Delete("1") if s2.Len() != 1 { t.Fatalf("Unexpected non-mutation of set")