package functional import ( "encoding/json" "sync" ) type Slice[T any] struct { s []T mu sync.Mutex } func NewSlice[T any]() *Slice[T] { return &Slice[T]{s: make([]T, 0)} } func NewSliceN[T any](n int) *Slice[T] { return &Slice[T]{s: make([]T, n)} } func NewSliceFrom[T any](s []T) *Slice[T] { return &Slice[T]{s: s} } func (s *Slice[T]) Size() int { return len(s.s) } func (s *Slice[T]) Empty() bool { return len(s.s) == 0 } func (s *Slice[T]) NotEmpty() bool { return len(s.s) > 0 } func (s *Slice[T]) Iterator() []T { return s.s } func (s *Slice[T]) Get(i int) T { return s.s[i] } func (s *Slice[T]) Set(i int, v T) { s.s[i] = v } func (s *Slice[T]) Add(e T) *Slice[T] { s.s = append(s.s, e) return s } func (s *Slice[T]) AddRange(other *Slice[T]) *Slice[T] { s.s = append(s.s, other.s...) return s } func (s *Slice[T]) SafeAdd(e T) *Slice[T] { s.mu.Lock() defer s.mu.Unlock() return s.Add(e) } func (s *Slice[T]) SafeAddRange(other *Slice[T]) *Slice[T] { s.mu.Lock() defer s.mu.Unlock() return s.AddRange(other) } func (s *Slice[T]) Pop() T { v := s.s[len(s.s)-1] s.s = s.s[:len(s.s)-1] return v } func (s *Slice[T]) SafePop() T { s.mu.Lock() defer s.mu.Unlock() return s.Pop() } func (s *Slice[T]) Remove(criteria func(T) bool) { for i, v2 := range s.s { if criteria(v2) { s.s = append(s.s[:i], s.s[i+1:]...) } } } func (s *Slice[T]) SafeRemove(criteria func(T) bool) { s.mu.Lock() defer s.mu.Unlock() s.Remove(criteria) } func (s *Slice[T]) ForEach(do func(T)) { for _, v := range s.s { do(v) } } func (s *Slice[T]) Map(m func(T) T) *Slice[T] { n := make([]T, len(s.s)) for i, v := range s.s { n[i] = m(v) } return &Slice[T]{s: n} } func (s *Slice[T]) Filter(f func(T) bool) *Slice[T] { n := make([]T, 0) for _, v := range s.s { if f(v) { n = append(n, v) } } return &Slice[T]{s: n} } func (s *Slice[T]) String() string { out, err := json.MarshalIndent(s.s, "", " ") if err != nil { panic(err) } return string(out) }