class SetHash
class SetHash does Setty { }
A SetHash
is a mutable set, meaning a collection of distinct elements in no
particular order. (For immutable sets, see Set instead.)
Objects/values of any type are allowed as set elements. Within a Set, every element is guaranteed to be unique (in the sense that no two elements would compare positively with the === operator):
my $fruits = <peach apple orange apple apple>.SetHash;
say $fruits.elems; # OUTPUT: «3»
say $fruits.keys.sort; # OUTPUT: «apple orange peach»
Just like Sets, SetHash
es can be treated as object hashes using the { }
postcircumfix operator, which returns the value True
for keys that are
elements of the set, and False
for keys that aren't.
my $fruits = <peach apple orange apple apple>.SetHash;
say $fruits<apple>; # OUTPUT: «True»
say $fruits<kiwi>; # OUTPUT: «False»
Unlike Sets, SetHash
es are mutable. You can add an item or list of items
to the SetHash
with the set
method and can remove an item or list of items
with the unset
method:
my $fruits = <peach>.SetHash;
$fruits.set('apple');
say $fruits; # OUTPUT: «SetHash(apple peach)»
$fruits.unset('peach');
say $fruits; # OUTPUT: «SetHash(apple)»
$fruits.set(<kiwi banana apple>);
say $fruits; # OUTPUT: «SetHash(apple banana kiwi)»
$fruits.unset(<apple banana kiwi>);
say $fruits; # OUTPUT: «SetHash()»
Be careful not to confuse the set
method, which adds an item to a SetHash
with the Set method, which converts the mutable SetHash
into an immutable
Set.
As an alternative to using the set
and unset
methods, you can also add or
remove set elements by assigning a value that boolifies to True
or False
,
respectively:
my $fruits = <peach apple orange>.SetHash;
$fruits<apple kiwi> = False, True;
say $fruits.keys.sort; # OUTPUT: «kiwi orange peach»
Here is a convenient shorthand idiom for adding and removing SetHash elements using assignment:
my SetHash $fruits .= new;
say $fruits<cherry>; # OUTPUT: «False»
$fruits<cherry>++;
say $fruits<cherry>; # OUTPUT: «True»
$fruits<apple banana kiwi>»++; # Add multiple elements
$fruits<cherry>--;
say $fruits<cherry>; # OUTPUT: «False»
$fruits<banana kiwi>»--; # Remove multiple elements
Creating SetHash
objects
SetHash
es can be composed using SetHash.new
. Any positional parameters,
regardless of their type, become elements of the set:
my $n = SetHash.new: "zero" => 0, "one" => 1, "two" => 2;
say $n.keys.raku; # OUTPUT: «(:two(2), :zero(0), :one(1)).Seq»
say $n.keys.map(&WHAT); # OUTPUT: «((Pair) (Pair) (Pair))»
Alternatively, the .SetHash
coercer (or its functional form, SetHash()
)
can be called on an existing object to coerce it to a SetHash
. Its semantics
depend on the type and contents of the object. In general it evaluates the
object in list context and creates a set with the resulting items as elements,
although for Hash-like objects or Pair items, only the keys become elements of
the set - and keys mapped to values which boolify to False
are skipped:
my $n = ("zero" => 0, "one" => 1, "two" => 2).SetHash;
say $n.keys.raku; # OUTPUT: «("one", "two").Seq»
say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))»
It is also possible to initialize a single key with the use of {}
:
my $sh = SetHash.new;
$sh{ 'key1' } = True;
$sh{ 'key2' } = 'Hello World!';
$sh{ 'key3' } = 0; # does not store the key since 0.Bool is False
say $sh; # OUTPUT: «SetHash(key1 key2)»
say $sh.keys.raku; # OUTPUT: «("key1", "key2").Seq»
or, in order to initialize more than one key at the same time, use a list assignment:
my $sh = SetHash.new;
$sh{ 'a', 'b', 'c' } = True, False, True;
say $sh.keys.raku; # OUTPUT: «("a", "c").Seq»
You can also create SetHash
masquerading as a hash by using the is
trait:
my %sh is SetHash = <a b c>;
say %sh<a>; # OUTPUT: «True»
say %sh<d>; # OUTPUT: «False»
Since 6.d (2019.03 and later) it is also possible to specify the type of values
you would like to allow in a SetHash
. This can either be done when calling
.new
:
# only allow Pairs
my $n = SetHash[Pair].new: "zero" => 0, "one" => 1, "two" => 2;
or using the masquerading syntax:
# only allow strings
my %sh is SetHash[Str] = <a b c>;
say %sh<a>; # OUTPUT: «True»
say %sh<d>; # OUTPUT: «False»
# only allow whole numbers
my %sh is SetHash[Int] = <a b c>;
# Type check failed in binding; expected Int but got Str ("a")
Operators
See Operators with set
semantics for a complete
list of "set operators" applicable to, among other types, SetHash
.
Examples:
my ($a, $b) = SetHash.new(1, 2, 3), SetHash.new(2, 4);
say $a (<) $b; # OUTPUT: «False»
say $a (&) $b; # OUTPUT: «SetHash(2)»
say $a (^) $b; # OUTPUT: «SetHash(1 3 4)»
say $a (|) $b; # OUTPUT: «SetHash(1 2 3 4)»
# Unicode versions:
say $a ⊂ $b; # OUTPUT: «False»
say $a ∩ $b; # OUTPUT: «SetHash(2)»
say $a ⊖ $b; # OUTPUT: «SetHash(1 3 4)»
say $a ∪ $b; # OUTPUT: «SetHash(1 2 3 4)»
Methods
method set
method set(SetHash:D: \to-set --> Nil)
When given single key, set
adds it to the SetHash
. When given a
List, Array, Seq, or any other type that does
the
Iterator Role, set
adds each element of the
Iterator as a key to the SetHash
.
Note: since version 2020.02.
method unset
method unset(SetHash:D: \to-unset --> Nil)
When given single key, unset
removes it from the SetHash
. When
given a List, Array, Seq, or any other type that does
the
Iterator Role, unset
removes each element of
the Iterator from the SetHash
(if it was present as a key).
Note: since version 2020.02.