Documentation
¶
Overview ¶
Package set is a pure-Go (no cgo) reimplementation of Ruby's MRI 4.0.5 Set — an unordered collection of unique members with full set algebra, mirroring the behaviour of the `set` standard library (autoloaded core in Ruby 4.0).
Element identity ¶
In MRI a Set keys its members by Ruby's hash / eql? protocol, so two distinct String objects with the same bytes are the *same* member, while a Symbol of the same name is a *different* member. Go cannot know those semantics, so the host supplies them through a Hasher: a function mapping a member to a comparable Go key under which two members are considered equal. go-embedded-ruby plugs its own object hashing here, exactly as it does for Hash keys.
A Set built with New (no Hasher) keys members by themselves and therefore only accepts comparable members — convenient for plain Go programs. A Set built with NewWith(hasher) keys members through the host function and accepts any value.
Ordering ¶
Like MRI, iteration (Each / ToSlice / Inspect) preserves first-insertion order. The set algebra keeps the receiver's order first, then the argument's, so the results match MRI's observable ordering.
Index ¶
- func DefaultInspect(elem any) string
- type ClassGroup
- type ClassifyResult
- type GroupByBucket
- type GroupByResult
- type Hasher
- type Set
- func (s *Set) Add(elem any) *Set
- func (s *Set) AddQ(elem any) bool
- func (s *Set) Classify(fn func(elem any) any) *ClassifyResult
- func (s *Set) Clear() *Set
- func (s *Set) CollectBang(fn func(elem any) any) *Set
- func (s *Set) Delete(elem any) *Set
- func (s *Set) DeleteQ(elem any) bool
- func (s *Set) Difference(other *Set) *Set
- func (s *Set) DisjointQ(other *Set) bool
- func (s *Set) Divide(fn func(elem any) any) []*Set
- func (s *Set) DivideRel(rel func(a, b any) bool) []*Set
- func (s *Set) Dup() *Set
- func (s *Set) Each(fn func(elem any) error) error
- func (s *Set) EachPair(fn func(key, member any))
- func (s *Set) Empty() bool
- func (s *Set) EqualQ(other *Set) bool
- func (s *Set) FlattenSet() *Set
- func (s *Set) GroupBy(fn func(elem any) any) *GroupByResult
- func (s *Set) Include(elem any) bool
- func (s *Set) Inspect(stringFn func(elem any) string) string
- func (s *Set) IntersectQ(other *Set) bool
- func (s *Set) Intersection(other *Set) *Set
- func (s *Set) Map(fn func(elem any) any) []any
- func (s *Set) Merge(others ...*Set) *Set
- func (s *Set) MergeSlice(elems []any) *Set
- func (s *Set) ProperSubsetQ(other *Set) bool
- func (s *Set) ProperSupersetQ(other *Set) bool
- func (s *Set) Reject(fn func(elem any) bool) *Set
- func (s *Set) Select(fn func(elem any) bool) *Set
- func (s *Set) Size() int
- func (s *Set) SortedSlice(less func(a, b any) bool) []any
- func (s *Set) String() string
- func (s *Set) SubsetQ(other *Set) bool
- func (s *Set) Subtract(other *Set) *Set
- func (s *Set) SubtractSlice(elems []any) *Set
- func (s *Set) SupersetQ(other *Set) bool
- func (s *Set) ToSlice() []any
- func (s *Set) Union(other *Set) *Set
- func (s *Set) XorSym(other *Set) *Set
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultInspect ¶
DefaultInspect renders a member with Go's %#v, a reasonable default when the host supplies no Ruby inspect.
Types ¶
type ClassGroup ¶
ClassGroup is one bucket of a Classify / GroupBy result: the block value that labels the bucket and the members assigned to it.
type ClassifyResult ¶
type ClassifyResult struct {
// contains filtered or unexported fields
}
ClassifyResult is the insertion-ordered Hash{value => Set} a Classify returns.
func (*ClassifyResult) Get ¶
func (r *ClassifyResult) Get(bv any, h Hasher) (*Set, bool)
Get returns the Set for block value bv and whether it exists.
func (*ClassifyResult) Groups ¶
func (r *ClassifyResult) Groups() []*ClassGroup
Groups returns the buckets in first-seen order (Ruby Hash insertion order).
type GroupByBucket ¶
GroupByBucket is one bucket of a GroupBy result.
type GroupByResult ¶
type GroupByResult struct {
// contains filtered or unexported fields
}
GroupByResult is the insertion-ordered Hash{value => Array} a GroupBy returns.
func (*GroupByResult) Buckets ¶
func (r *GroupByResult) Buckets() []*GroupByBucket
Buckets returns the buckets in first-seen order.
type Hasher ¶
Hasher maps a member to the comparable key under which membership and equality are decided. Two members are the same iff their keys are ==. The host (e.g. go-embedded-ruby) supplies Ruby hash / eql? semantics here; a nil Hasher keys a member by itself (the member must then be comparable, or operations panic, just as a Go map does on an uncomparable key).
type Set ¶
type Set struct {
// contains filtered or unexported fields
}
Set is an MRI-faithful Ruby Set: an unordered collection of unique members with set algebra, iterated in first-insertion order. The zero value is not usable; construct one with New or NewWith.
The members are held as two parallel insertion-ordered slices — keys[i] is the identity key of members[i] — plus a membership index from key to presence. Iteration (Each / ToSlice / the algebra source loops) walks the slices directly, so a member is never re-fetched through a map lookup; the index is consulted only for membership tests. When the Hasher is nil a key is its own member, so the two slices hold the same values but are kept distinct to keep the hashed and unhashed paths uniform.
The membership index (see membership) keeps a concrete-typed map for the common homogeneous key types (all int, all int64, all string) and falls back to a generic map[any] only for mixed or other-typed sets, so the frequent case avoids interface-hashing every key while every Ruby-observable semantic — including the distinctness of int(1), int64(1), 1.0 and "1" — is preserved.
func New ¶
New returns a Set keyed by member identity (members must be comparable), seeded with the given members. It is the convenient form for plain Go data.
func NewWith ¶
NewWith returns a Set whose membership and equality are decided by h, seeded with the given members. A nil h keys members by themselves (like New). This is the form a host with Ruby hash / eql? semantics uses. The internal tables are pre-grown for the seed count, so seeding a known number of members neither rehashes the index nor re-grows the order slices.
func (*Set) Add ¶
Add inserts elem, returning the Set for chaining (Ruby Set#add / #<<). Adding a member already present is a no-op that preserves the original member.
func (*Set) AddQ ¶
AddQ adds elem and reports whether it was newly inserted (Ruby Set#add?: self when added, nil when already present — modelled here as a bool).
func (*Set) Classify ¶
func (s *Set) Classify(fn func(elem any) any) *ClassifyResult
Classify groups the members by fn(member), returning a map from each block value's key to the Set of members that produced it (Ruby Set#classify returns a Hash{value => Set}). The returned map is keyed by the *key* of each block value (under the receiver's Hasher) so distinct-but-equal Ruby values coincide; the ClassifyResult also records the original block value for each group.
func (*Set) CollectBang ¶
CollectBang replaces every member with fn(member) in place, returning the receiver for chaining (Ruby Set#collect! / #map!). The set is rebuilt, so two members mapping to the same key collapse to one.
func (*Set) Delete ¶
Delete removes elem, returning the Set for chaining (Ruby Set#delete). Deleting an absent member is a no-op.
func (*Set) DeleteQ ¶
DeleteQ removes elem and reports whether it was present (Ruby Set#delete?: self when removed, nil when absent — modelled here as a bool).
func (*Set) Difference ¶
Difference returns a new Set with the receiver's members not in other (Ruby Set#- / #difference). Order follows the receiver.
func (*Set) DisjointQ ¶
DisjointQ reports whether the two sets share no member (Ruby Set#disjoint?).
func (*Set) Divide ¶
Divide partitions the members into a Set of Sets by the single-argument relation fn: members sharing the same fn value land in the same block (Ruby Set#divide with an arity-1 block). For the transitive-closure (binary) form, use DivideRel.
func (*Set) DivideRel ¶
DivideRel partitions the members into connected components of the graph whose edges are the pairs (a, b) for which rel(a, b) is true (Ruby Set#divide with an arity-2 block — a transitive-closure partition). rel is treated as symmetric: an edge a—b is added when rel(a, b) or rel(b, a) holds.
func (*Set) Dup ¶
Dup returns a shallow copy with the same members in the same order and the same Hasher (Ruby Set#dup / #clone).
func (*Set) Each ¶
Each calls fn for every member in insertion order (Ruby Set#each). Returning a non-nil error from fn stops iteration and propagates it. It walks the member slice directly — no per-element map lookup.
func (*Set) EachPair ¶
EachPair calls fn for every member in insertion order with both its identity key and the stored member value, in a single pass over the internal tables — no per-element membership re-lookup. A host that retains its own per-member data keyed by the identity key (as go-embedded-ruby does for the original Ruby value) can consume an algebra result with EachPair to rebuild its view in one pass, instead of re-deriving each member's key and re-testing Include. The members are exactly those yielded by Each / ToSlice, in the same order.
func (*Set) FlattenSet ¶
FlattenSet returns a new Set in which every member that is itself a *Set is replaced by its members, recursively (Ruby Set#flatten). The receiver is unchanged; the result uses the receiver's Hasher.
func (*Set) GroupBy ¶
func (s *Set) GroupBy(fn func(elem any) any) *GroupByResult
GroupBy groups the members by fn(member) like Classify, but each bucket holds a slice in insertion order rather than a Set (Ruby Enumerable#group_by returns a Hash{value => Array}).
func (*Set) Include ¶
Include reports whether elem is a member (Ruby Set#include? / #member? / #===).
func (*Set) Inspect ¶
Inspect renders the Set in MRI 4.0 form: "Set[1, 2, 3]" (an empty set is "Set[]"), members in insertion order via stringFn. stringFn produces each member's Ruby inspect; pass DefaultInspect for Go's %#v rendering.
func (*Set) IntersectQ ¶
IntersectQ reports whether the two sets share at least one member (Ruby Set#intersect?), the negation of DisjointQ.
func (*Set) Intersection ¶
Intersection returns a new Set with the members in both (Ruby Set#& / #intersection). Order follows the receiver. It scans the smaller operand so the work is bounded by the smaller size, mapping back to the receiver's order when the receiver is the larger one.
func (*Set) Map ¶
Map applies fn to each member in insertion order and returns the results as a slice (Ruby Set#map / #collect returns an Array, not a Set).
func (*Set) Merge ¶
Merge adds every member of each other Set, returning the receiver for chaining (Ruby Set#merge). The receiver is mutated.
func (*Set) MergeSlice ¶
MergeSlice adds every element of the slice, returning the receiver for chaining (Ruby Set#merge accepts any enumerable; this is the slice form).
func (*Set) ProperSubsetQ ¶
ProperSubsetQ reports whether the receiver is a subset of other and not equal to it (Ruby Set#proper_subset? / #<).
func (*Set) ProperSupersetQ ¶
ProperSupersetQ reports whether the receiver is a superset of other and not equal to it (Ruby Set#proper_superset? / #>).
func (*Set) Reject ¶
Reject returns a new Set of the members for which fn is false (Ruby Set#reject).
func (*Set) Select ¶
Select returns a new Set of the members for which fn is true (Ruby Set#select / #filter).
func (*Set) SortedSlice ¶
SortedSlice returns the members sorted by less, leaving the Set unchanged. MRI 4.0 dropped the SortedSet class from core (Set#sort returns an Array), so this is the faithful equivalent of Ruby's Set#sort.
func (*Set) SubsetQ ¶
SubsetQ reports whether every member of the receiver is in other (Ruby Set#subset? / #<=).
func (*Set) Subtract ¶
Subtract removes every member of other, returning the receiver for chaining (Ruby Set#subtract). The receiver is mutated.
func (*Set) SubtractSlice ¶
SubtractSlice removes every element of the slice, returning the receiver for chaining (Ruby Set#subtract accepts any enumerable; this is the slice form).
func (*Set) SupersetQ ¶
SupersetQ reports whether every member of other is in the receiver (Ruby Set#superset? / #>=).
func (*Set) Union ¶
Union returns a new Set with the members of the receiver and other (Ruby Set#| / #+ / #union). The receiver's order comes first, then other's. It fills in a single pass over each operand with a result map pre-grown to the worst-case size, so neither operand's members are re-hashed by an Add probe.
