6.35 Sets
Immutable sets can be constructed using the syntax {val_expr, ...}, which creates a set containing the values of the val_exprs. More precisely, a use of curly braces with no preceding expression is parsed as an implicit use of the #%braces form.
A set is indexable, and […] after a set expression with an expression for a value checks for membership: the result is a boolean indicating whether the value is in the set. Mutable sets can be updated with a combination of […] and the := operator, where a #false result on the right-hand side of := removes an element from a set, and any other right-hand side result causes the value to be included in the set. (Use ++ to functionally add to an immutable set.) These uses of […] are implemented by #%index. A set can be used as sequence, in which case it supplies its elements in an unspecified order.
st.length()
is
Set.length(st)
st.get(v)
is
Set.get(st, v)
is
Set.to_list(st, try_sort, ...)
st.copy()
is
Set.copy(st)
st.snapshot()
is
Set.snapshot(st)
st.to_sequence()
is
Set.to_sequence(st)
is
Set.append(st, st2, ...)
is
is
Set.intersect(st, st2, ...)
st.remove(v)
is
Set.remove(st, v)
st.set(v, in)
is
MutableSet.set(st, v, in)
st.delete(v)
is
MutableSet.delete(st, v)
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
The of and now_of annotation variants match a set whose elements satisfy annot, where satisfaction of the annotation is confirmed by immediately checking all elements. No future obligation is attached to a set satisfying the annotation, so in the case of MutableSet.now_of, no static information is associated with value access using […].
The later_of annotation variants create a converter annotation given an annotations for elements; satisfaction of those annotations is confirmed only on demand, both for elements that are extracted from the set and for elements added or appended to the set. For Set.later_of, the key and value annotations must be predicate annotations. Since an element annotation is checked on every access, its static information is associated with access using […].
The Set.by and MutableSet.by annotation variants match only sets that use the hash and equality procedures specified by key_comp.
Static information associated by Set, etc., makes an expression acceptable to for in static mode.
expression | |||||||||
Set{expr_or_splice, ...} | |||||||||
| |||||||||
repetition | |||||||||
Set{repet_or_splice, ...} | |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
function | |||||||||
| |||||||||
expression | |||||||||
Set.by(key_comp){expr_or_splice, ...} | |||||||||
| |||||||||
expression | |||||||||
| |||||||||
repetition | |||||||||
Note that Set{} and Set() produce an empty set while {…} does not, since {} produces an empty map instead.
The Set.by variants create a map that uses the equality and hashing functions specified by key_comp.
> s
{1, 2, "x", "y"}
> s["x"]
#true
> s[1]
#true
> s[42]
#false
> Set("x", 1, "y", 2)
{1, 2, "x", "y"}
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
ReadableSet{expr, ...} | ||||||
| ||||||
binding operator | ||||||
ReadableSet{expr, ..., rest} | ||||||
| ||||||
binding operator | ||||||
ReadableSet(expr, ...) | ||||||
| ||||||
binding operator | ||||||
ReadableSet(expr, ..., rest) | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
| ||||||
| ||||||
|
The Set binding forms match only immutable sets, while ReadableSet forms match both immutable and mutable sets. For ReadableSet, the & set_bind will match a snapshot (in the sense of Set.snapshot) of the rest of the set. The Set.by binding forms match only immutable sets constructed using key_comp.
def: value does not satisfy annotation
value: {"x"}
annotation: matching(Set{"x", "y"})
> rst
{"b", "c"}
> [val, ...]
["b", "c"]
reducer |
expression |
MutableSet{val_expr, ...} |
|
function |
fun MutableSet(val :: Any, ...) :: MutableSet |
|
expression |
MutableSet.by(key_comp){val_expr, ...} |
|
expression |
Note that ... and & are not supported for construction mutable sets, only immutable sets.
> def m = MutableSet{"x", 1, "y", 2}
> m
MutableSet{1, 2, "x", "y"}
> m["x"]
#true
> m["x"] := #false
> m
MutableSet{1, 2, "y"}
> m["x"] := #true
> m
MutableSet{1, 2, "x", "y"}
expression |
WeakMutableSet{val_expr, ...} |
|
function |
fun WeakMutableSet(val :: Any, ...) :: MutableSet |
|
expression |
WeakMutableSet.by(key_comp){val_expr, ...} |
|
expression |
value |
|
binding operator |
|
value |
|
binding operator |
The ReadableSet.empty binding form matches an empty set whether it is mutable or immutable.
Corresponding to the binding forms, Set.empty and ReadableSet.empty are bound to Set{} with appropriate static information.
Set{}
| Set.empty: "empty set"
| _: #false
"empty set"
> match MutableSet()
| Set.empty: "empty immutable set"
| _: #false
#false
> match MutableSet()
| ReadableSet.empty: "empty set for now"
| _: #false
"empty set for now"
function |
fun Set.length(st :: ReadableSet) :: Int |
> Set.length({"a", "b"})
2
> Set.length(Set{})
0
> {"a", "b"}.length()
2
0
> {"a", "b"}.get("a")
#true
> {"a", "b"}["a"]
#true
function |
|
function |
|
function |
> {1, 2, 3}.append({2, 3}, {3, 4})
{1, 2, 3, 4}
> {1, 2, 3}.union({2, 3}, {3, 4})
{1, 2, 3, 4}
> {1, 2, 3}.intersect({2, 3}, {3, 4})
{3}
> {1, 2, 3}.remove(2)
{1, 3}
> {1, 2, 3}.remove(4)
{1, 2, 3}
function | |||
> def s = MutableSet{1, 2, 3}
> s.set(1, #false)
> s
MutableSet{2, 3}
> s[1] := #true
> s
MutableSet{1, 2, 3}
function | ||
|
> def s = MutableSet{1, 2, 3}
> s.delete(2)
> s
MutableSet{1, 3}
function | |||
|
> {1, 2, 3}.to_list(#true)
[1, 2, 3]
function |
fun Set.copy(st :: ReadableSet) :: MutableSet |
function |
fun Set.snapshot(st :: ReadableSet) :: Set |
function |