kex docs Standard Library

Data.Set

module Data

Immutable collections of distinct elements.

Opt-in: nothing here is in scope until using Data.Set, which brings both flavours below into scope at once.

using Data.Set

Membership is decided by structural equality: the same equality == and map keys use, so records and tuples are compared by value, not identity. Every method answers with a new set; the ! forms (add!, delete!) build a new set and rebind the receiver variable rather than modifying anything in place.

let tags = Set.from(["kex", "beam", "kex"])
tags.count                     # => 2
tags.contains?("beam")         # => true
tags.add("erlang").items       # => ["beam", "erlang", "kex"]

There are two flavours, differing only in how they store their elements:

Set           sorted, so iteration is in ascending element order and the
              elements must be Orderable.
UnorderedSet  hash-backed, so membership does not pay for ordering and
              the elements need only be comparable. Iteration order is
              unspecified: never write a test against it.

Reach for Set when you will read the elements back out, and for UnorderedSet when the set exists to answer contains? quickly.

== between two sets needs no overload of its own: each flavour keeps its backing canonical (sorted and duplicate free, or a map) so comparing the records structurally already IS set equality.

Both wrap structures the runtime already has (a list and a map), so no set is opaque: .items is always a real list you can hand to anything.

Those two backings are also the ones the BEAM's own set libraries use: a Set is laid out exactly like an ordsets term and an UnorderedSet exactly like a sets v2 term, so the operations here can be routed to the native BIFs later without changing what a set IS. What rules out adopting gb_sets instead is the other backend: a tree-walk interpreter cannot produce an opaque BEAM term, and a set that only one backend can build is not a set the prelude can offer.

record Set<A>

A set whose elements are kept sorted and duplicate free.

Build one with Set.from rather than by hand: the record literal does no deduplication and no sorting, and every method here relies on both. Reading items back is the field itself, so handing a set's elements to list code costs nothing.

Set.from([3, 1, 2]).items   # => [1, 2, 3]

Fields

items
[A] optional

Implements Enumerable, Foldable, Monoid, Showable, Blankable.

Methods

reduce Enumerable Foldable

reduce(acc: B, f: (B -> A -> B)) -> B

Folds over the elements in ascending order.

This is Set's Enumerable primitive; each, find, any? and the rest are built on it. The collection-returning operations are overridden below, because Enumerable's defaults answer with a list.

Parameters
acc
the initial accumulator
f
combines the accumulator with each element

Returns the final accumulator

Examples
Set.from([1, 2, 3]).reduce(0) { |sum, x| sum + x }   # => 6

identity Monoid

identity : Set<A>

The empty set: the Monoid identity, since union with nothing changes nothing.

Returns the empty set

combine Monoid

combine(other: Set<A>) -> Set<A>

Combines two sets by union. The Monoid operation.

Parameters
other
the set to combine with

Returns every element of either set

Examples

Merging many sets into one

[Set.from([1]), Set.from([2]), Set.from([1, 3])]
  .reduce(Set.empty) { |acc, s| acc.combine(s) }
# => Set(1, 2, 3)

contains?

contains?(value: A) -> Bool

Returns true when value is a member.

Parameters
value
the element to look for

Returns true when it is present

Examples
Set.from([1, 2, 3]).contains?(2)   # => true
Set.from([1, 2, 3]).contains?(9)   # => false

Filtering a list against an allow-list

let allowed = Set.from(["get", "post"])
methods.filter { |m| allowed.contains?(m.lowerCase) }

count Foldable

count : Integer

Returns the number of distinct elements. Duplicates in the source list were already discarded, so this is the size of the set, not of what it was built from.

Returns the number of elements

Examples
Set.from([1, 1, 2]).count   # => 2

Counting distinct words

Set.from(text.split(" ")).count

empty?

empty? : Bool

Returns true when the set has no elements.

Returns true for the empty set

Examples
Set.empty.empty?           # => true
Set.from([1]).empty?       # => false

add

add(value: A) -> Set<A>

Returns a new set with value added. Adding an element that is already a member changes nothing: that is what makes a set a set.

Use add! to rebind the receiver variable.

Parameters
value
the element to add

Returns a set including value

Examples
Set.from([1, 2]).add(3)   # => Set(1, 2, 3)
Set.from([1, 2]).add(2)   # => Set(1, 2)

Accumulating as you go

var seen = Set.empty
ids.each { |id| seen.add!(id) }

delete

delete(value: A) -> Set<A>

Returns a new set without value. Removing something that is not a member changes nothing.

Use delete! to rebind the receiver variable.

Parameters
value
the element to remove

Returns a set without value

Examples
Set.from([1, 2, 3]).delete(2)   # => Set(1, 3)
Set.from([1, 2, 3]).delete(9)   # => Set(1, 2, 3)

union

union(other: Set<A>) -> Set<A>

Returns every element of either set.

Parameters
other
the other set

Returns the union

Examples
Set.from([1, 2]).union(Set.from([2, 3]))   # => Set(1, 2, 3)

Collecting every tag used across posts

posts.reduce(Set.empty) { |all, p| all.union(Set.from(p.tags)) }

intersect

intersect(other: Set<A>) -> Set<A>

Returns the elements both sets have.

Parameters
other
the other set

Returns the intersection

Examples
Set.from([1, 2, 3]).intersect(Set.from([2, 3, 4]))   # => Set(2, 3)
Set.from([1]).intersect(Set.from([2]))               # => Set()

Which requested permissions the user actually has

requested.intersect(granted)

difference

difference(other: Set<A>) -> Set<A>

Returns the elements of this set that other does not have.

Order matters: a.difference(b) and b.difference(a) are different questions. Use symmetricDifference when you want both answers.

Parameters
other
the set to subtract

Returns the elements only this set has

Examples
Set.from([1, 2, 3]).difference(Set.from([2]))   # => Set(1, 3)

Which required fields are still missing

required.difference(Set.from(form.keys))

symmetricDifference

symmetricDifference(other: Set<A>) -> Set<A>

Returns the elements in exactly one of the two sets: everything they do not agree on.

Parameters
other
the other set

Returns the symmetric difference

Examples
Set.from([1, 2]).symmetricDifference(Set.from([2, 3]))   # => Set(1, 3)

What changed between two snapshots

before.symmetricDifference(after)

subset?

subset?(other: Set<A>) -> Bool

Returns true when every element of this set is also in other. The empty set is a subset of everything.

Parameters
other
the candidate superset

Returns true when this set is contained in other

Examples
Set.from([1, 2]).subset?(Set.from([1, 2, 3]))   # => true
Set.from([1, 9]).subset?(Set.from([1, 2, 3]))   # => false

An authorisation check

required.subset?(granted)

superset?

superset?(other: Set<A>) -> Bool

Returns true when this set has every element of other. The mirror image of subset?.

Parameters
other
the candidate subset

Returns true when this set contains all of other

Examples
Set.from([1, 2, 3]).superset?(Set.from([1, 2]))   # => true
Set.from([1, 2]).superset?(Set.from([1, 9]))      # => false

disjoint?

disjoint?(other: Set<A>) -> Bool

Returns true when the two sets share no element.

Parameters
other
the other set

Returns true when the intersection is empty

Examples
Set.from([1, 2]).disjoint?(Set.from([3]))      # => true
Set.from([1, 2]).disjoint?(Set.from([2, 3]))   # => false

Checking that two rulesets cannot both apply

allowList.disjoint?(denyList)

+

+(other: Set<A>) -> Set<A>
+(other: [A]) -> Set<A>

Unions with another set, or with a plain list.

The list form is the everyday way to add one element without naming a method: +s + [x]+.

Parameters
other
the elements to add

Returns the union

Examples
Set.from([1, 2]) + [3]           # => Set(1, 2, 3)
Set.from([1]) + Set.from([2])    # => Set(1, 2)

-

-(other: Set<A>) -> Set<A>
-(other: [A]) -> Set<A>

Removes another set's elements, or a plain list's.

Parameters
other
the elements to remove

Returns the difference

Examples
Set.from([1, 2, 3]) - [2]                # => Set(1, 3)
Set.from([1, 2, 3]) - Set.from([2, 3])   # => Set(1)

map Enumerable

map(f: (A -> B)) -> Set<B>

Applies f to every element and returns a set of the results.

Mapping a set may collapse elements: if f sends two members to the same value, the result has one. That is not a loss of information so much as the point of a set: Set.from([1, -1]).map(~abs) has one member.

Parameters
f
applied to each element

Returns the distinct results

Examples
Set.from([1, 2, 3]).map { |x| x * 2 }   # => Set(2, 4, 6)
Set.from([1, -1]).map { |x| x.abs }     # => Set(1)

Collecting the distinct extensions in a file list

Set.from(paths).map { |p| p.split(".").last.or("") }

filter Enumerable

filter(pred: (A -> Bool)) -> Set<A>

Returns a new set with only the elements pred accepts.

Parameters
pred
the test applied to each element

Returns the matching elements

Examples
Set.from([1, 2, 3]).filter { |x| x > 1 }   # => Set(2, 3)

reject

reject(pred: (A -> Bool)) -> Set<A>

Returns a new set without the elements pred accepts. The complement of filter.

Parameters
pred
the test applied to each element

Returns the elements that failed the predicate

Examples
Set.from([1, 2, 3]).reject { |x| x > 1 }   # => Set(1)

showValue Showable

showValue : String

Renders the set as Set(...) in element order, rather than exposing the record layout behind it.

Returns the rendered set

Examples
Set.from([2, 1]).showValue   # => "Set(1, 2)"

blank? Blankable

blank? : Bool

Returns true when the set has no elements. The Blankable view of empty?, so generic code can test a set the same way it tests a string.

Returns true for the empty set

Examples
Set.empty.blank?         # => true
Set.from([1]).blank?     # => false

From Enumerable

mapIndexed
Applies f to each item and its 0-based position, and collects the results into a list.
flatMap
Applies f to each item, expecting a list back, and concatenates the results into one flat list.
collect
Applies f to each item, expecting an Optional back, and returns the values that were present: unwrapped.

From Foldable

each
Calls f with each item, for its side effects.
eachIndexed
Calls f with each item and its 0-based position, for its side effects.
all?
Returns true when every item satisfies pred.
any?
Returns true when at least one item satisfies pred.
find
Returns the first item satisfying pred, or None when nothing does.

From Monoid

repeat
Combines this value with itself n times.

From Showable

record UnorderedSet<A>

A set backed by a map from each member to true; its keys ARE the elements.

Build one with UnorderedSet.from. Iteration order is whatever the map hands back, so use items.sort when you need a stable order.

UnorderedSet.from([3, 1, 2]).contains?(2)   # => true

Fields

slots
{A: Bool} optional

Implements Enumerable, Foldable, Monoid, Showable, Blankable.

Methods

reduce Enumerable Foldable

reduce(acc: B, f: (B -> A -> B)) -> B

Folds over the elements.

The order is whatever the underlying map hands back: unspecified, and not to be relied on. Use a Set when the order of the fold matters.

Parameters
acc
the initial accumulator
f
combines the accumulator with each element

Returns the final accumulator

Examples
UnorderedSet.from([1, 2, 3]).reduce(0) { |sum, x| sum + x }   # => 6

identity Monoid

identity : UnorderedSet<A>

The empty unordered set: the Monoid identity.

Returns the empty set

combine Monoid

combine(other: UnorderedSet<A>) -> UnorderedSet<A>

Combines two sets by union. The Monoid operation.

Parameters
other
the set to combine with

Returns every element of either set

contains?

contains?(value: A) -> Bool

Returns true when value is a member.

This is the operation the flavour exists for: a map lookup, with no ordering to maintain.

Parameters
value
the element to look for

Returns true when it is present

Examples
UnorderedSet.from([1, 2, 3]).contains?(2)   # => true
UnorderedSet.from([1, 2, 3]).contains?(9)   # => false

count Foldable

count : Integer

Returns the number of distinct elements.

Returns the number of elements

Examples
UnorderedSet.from([1, 1, 2]).count   # => 2

empty?

empty? : Bool

Returns true when the set has no elements.

Returns true for the empty set

Examples
UnorderedSet.empty.empty?   # => true

items

items : [A]

Returns the elements as a list, in unspecified order.

Sort the result when the order has to be stable: a test, a rendering, a comparison.

Returns the elements

Examples
UnorderedSet.from([3, 1, 2]).items.sort   # => [1, 2, 3]

add

add(value: A) -> UnorderedSet<A>

Returns a new set with value added. Adding an existing member changes nothing.

Use add! to rebind the receiver variable.

Parameters
value
the element to add

Returns a set including value

Examples
UnorderedSet.from([1]).add(2).count   # => 2
UnorderedSet.from([1]).add(1).count   # => 1

delete

delete(value: A) -> UnorderedSet<A>

Returns a new set without value. Removing a non-member changes nothing.

Use delete! to rebind the receiver variable.

Parameters
value
the element to remove

Returns a set without value

Examples
UnorderedSet.from([1, 2]).delete(1).count   # => 1

union

union(other: UnorderedSet<A>) -> UnorderedSet<A>

Returns every element of either set.

Parameters
other
the other set

Returns the union

Examples
UnorderedSet.from([1, 2]).union(UnorderedSet.from([2, 3])).count   # => 3

intersect

intersect(other: UnorderedSet<A>) -> UnorderedSet<A>

Returns the elements both sets have.

Parameters
other
the other set

Returns the intersection

Examples
UnorderedSet.from([1, 2, 3]).intersect(UnorderedSet.from([2, 3, 4])).items.sort
# => [2, 3]

difference

difference(other: UnorderedSet<A>) -> UnorderedSet<A>

Returns the elements of this set that other does not have.

Parameters
other
the set to subtract

Returns the elements only this set has

Examples
UnorderedSet.from([1, 2, 3]).difference(UnorderedSet.from([2])).items.sort
# => [1, 3]

symmetricDifference

symmetricDifference(other: UnorderedSet<A>) -> UnorderedSet<A>

Returns the elements in exactly one of the two sets.

Parameters
other
the other set

Returns the symmetric difference

Examples
UnorderedSet.from([1, 2]).symmetricDifference(UnorderedSet.from([2, 3])).items.sort
# => [1, 3]

subset?

subset?(other: UnorderedSet<A>) -> Bool

Returns true when every element of this set is also in other.

Parameters
other
the candidate superset

Returns true when this set is contained in other

Examples
UnorderedSet.from([1, 2]).subset?(UnorderedSet.from([1, 2, 3]))   # => true

superset?

superset?(other: UnorderedSet<A>) -> Bool

Returns true when this set has every element of other.

Parameters
other
the candidate subset

Returns true when this set contains all of other

Examples
UnorderedSet.from([1, 2, 3]).superset?(UnorderedSet.from([1, 2]))   # => true

disjoint?

disjoint?(other: UnorderedSet<A>) -> Bool

Returns true when the two sets share no element.

Parameters
other
the other set

Returns true when the intersection is empty

Examples
UnorderedSet.from([1, 2]).disjoint?(UnorderedSet.from([3]))   # => true

+

+(other: UnorderedSet<A>) -> UnorderedSet<A>
+(other: [A]) -> UnorderedSet<A>

Unions with another unordered set, or with a plain list.

Parameters
other
the elements to add

Returns the union

Examples
(UnorderedSet.from([1, 2]) + [3]).count   # => 3

-

-(other: UnorderedSet<A>) -> UnorderedSet<A>
-(other: [A]) -> UnorderedSet<A>

Removes another unordered set's elements, or a plain list's.

Parameters
other
the elements to remove

Returns the difference

Examples
(UnorderedSet.from([1, 2, 3]) - [2]).count   # => 2

map Enumerable

map(f: (A -> B)) -> UnorderedSet<B>

Applies f to every element and returns an unordered set of the results. Elements that map to the same value collapse into one.

Parameters
f
applied to each element

Returns the distinct results

Examples
UnorderedSet.from([1, 2, 3]).map { |x| x * 2 }.items.sort   # => [2, 4, 6]

filter Enumerable

filter(pred: (A -> Bool)) -> UnorderedSet<A>

Returns a new unordered set with only the elements pred accepts.

Parameters
pred
the test applied to each element

Returns the matching elements

Examples
UnorderedSet.from([1, 2, 3]).filter { |x| x > 1 }.items.sort   # => [2, 3]

reject

reject(pred: (A -> Bool)) -> UnorderedSet<A>

Returns a new unordered set without the elements pred accepts.

Parameters
pred
the test applied to each element

Returns the elements that failed the predicate

Examples
UnorderedSet.from([1, 2, 3]).reject { |x| x > 1 }.items   # => [1]

showValue Showable

showValue : String

Renders the set as UnorderedSet(...).

The elements are printed in sorted order where they allow it, so the rendering of a value is not at the mercy of map internals.

Returns the rendered set

Examples
UnorderedSet.from([2, 1]).showValue   # => "UnorderedSet(1, 2)"

blank? Blankable

blank? : Bool

Returns true when the set has no elements. The Blankable view of empty?.

Returns true for the empty set

Examples
UnorderedSet.empty.blank?   # => true

From Enumerable

mapIndexed
Applies f to each item and its 0-based position, and collects the results into a list.
flatMap
Applies f to each item, expecting a list back, and concatenates the results into one flat list.
collect
Applies f to each item, expecting an Optional back, and returns the values that were present: unwrapped.

From Foldable

each
Calls f with each item, for its side effects.
eachIndexed
Calls f with each item and its 0-based position, for its side effects.
all?
Returns true when every item satisfies pred.
any?
Returns true when at least one item satisfies pred.
find
Returns the first item satisfying pred, or None when nothing does.

From Monoid

repeat
Combines this value with itself n times.

From Showable

module Data.Set

Constructors for the sorted Set.

from

from(items: [A]) -> Set<A>

Builds a sorted set from a list, discarding duplicates.

This is the normal way to make a Set. Deduplication goes through a map rather than List.uniq: map keys are unique under exactly the structural equality a set wants, and each element costs one insertion instead of a scan of everything kept so far.

Parameters
items
the elements, in any order and with any duplicates

Returns the distinct elements, sorted

Examples
Set.from([3, 1, 2, 3])    # => Set(1, 2, 3)
Set.from("hello".chars)   # => Set(e, h, l, o)

Removing duplicates from a list

Set.from(["b", "a", "b"]).items   # => ["a", "b"]

empty constant

empty : Set<A>

The set with no elements. Also the Monoid identity, so s.combine(Set.empty) is s.

Examples
Set.empty.empty?   # => true
Set.empty.add(1)   # => Set(1)

module Data.UnorderedSet

Constructors for the hash-backed UnorderedSet.

from

from(items: [A]) -> UnorderedSet<A>

Builds an unordered set from a list, discarding duplicates.

Nothing is sorted, so unlike Set.from this does not require the elements to be Orderable.

Parameters
items
the elements, in any order and with any duplicates

Returns the distinct elements

Examples
UnorderedSet.from([3, 1, 2, 3]).count   # => 3

A fast membership test over a large list

let stopWords = UnorderedSet.from(["the", "a", "of"])
words.reject { |w| stopWords.contains?(w) }

empty constant

empty : UnorderedSet<A>

The unordered set with no elements. Also the Monoid identity.

Examples
UnorderedSet.empty.empty?   # => true