txt: ## sethash.md
  class SetHash
  
  Mutable collection of distinct objects
  
  ```raku
  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`](/type/Set) instead.)
  
  Objects/values of any type are allowed as set elements. Within a [`Set`](/type/Set), every element is guaranteed to be unique (in the sense that no two elements would compare positively with the [===](/routine/===) operator):
  
  ```raku
  my $fruits = <peach apple orange apple apple>.SetHash;
  
  say $fruits.elems;      # OUTPUT: «3␤»
  say $fruits.keys.sort;  # OUTPUT: «apple orange peach␤»
  
  ```
  
  Just like [`Set`](/type/Set)s, `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.
  
  ```raku
  my $fruits = <peach apple orange apple apple>.SetHash;
  
  say $fruits<apple>;     # OUTPUT: «True␤»
  say $fruits<kiwi>;      # OUTPUT: «False␤»
  
  ```
  
  Unlike [`Set`](/type/Set)s, `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:
  
  ```raku
  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`](/type/Set) method, which converts the mutable `SetHash` into an immutable [`Set`](/type/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:
  
  ```raku
  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:
  
  ```raku
  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](#class_SetHash "go to top of document")[§](#Creating_SetHash_objects "direct link")
  
  `SetHash`es can be composed using `SetHash.new`. Any positional parameters, regardless of their type, become elements of the set:
  
  ```raku
  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:
  
  ```raku
  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 `{}`:
  
  ```raku
  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:
  
  ```raku
  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:
  
  ```raku
  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`:
  
  ```raku
  # only allow Pairs
  my $n = SetHash[Pair].new: "zero" => 0, "one" => 1, "two" => 2;
  ```
  
  or using the masquerading syntax:
  
  ```raku
  # 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](#class_SetHash "go to top of document")[§](#Operators "direct link")
  
  See [Operators with set semantics](/language/setbagmix#Operators_with_set_semantics) for a complete list of "set operators" applicable to, among other types, `SetHash`.
  
  Examples:
  
  ```raku
  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](#class_SetHash "go to top of document")[§](#Methods "direct link")
  
  ## [method set](#class_SetHash "go to top of document")[§](#method_set "direct link")
  
  ```raku
  method set(SetHash:D: \to-set --> Nil)
  ```
  
  When given single key, `set` adds it to the `SetHash`. When given a [`List`](/type/List), [`Array`](/type/Array), [`Seq`](/type/Seq), or any other type that `does` the [`Iterator`](/type/Iterator) Role, `set` adds each element of the [`Iterator`](/type/Iterator) as a key to the `SetHash`.
  
  *Note:* since version 2020.02.
  
  ## [method unset](#class_SetHash "go to top of document")[§](#method_unset "direct link")
  
  ```raku
  method unset(SetHash:D: \to-unset --> Nil)
  ```
  
  When given single key, `unset` removes it from the `SetHash`. When given a [`List`](/type/List), [`Array`](/type/Array), [`Seq`](/type/Seq), or any other type that `does` the [`Iterator`](/type/Iterator) Role, `unset` removes each element of the [`Iterator`](/type/Iterator) from the `SetHash` (if it was present as a key).
  
  *Note:* since version 2020.02.
  
  # [See Also](#class_SetHash "go to top of document")[§](#See_Also "direct link")
  
  [Sets, Bags, and Mixes](/language/setbagmix)
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `SetHash`
  
  
  
  raku-type-graph
  
  
  
  SetHash
  SetHash
  
  
  Any
  Any
  
  
  SetHash->Any
  
  
  
  Setty
  Setty
  
  
  SetHash->Setty
  
  
  
  Mu
  Mu
  
  
  Any->Mu
  
  
  
  Associative
  Associative
  
  
  QuantHash
  QuantHash
  
  
  QuantHash->Associative
  
  
  
  Setty->QuantHash
  
  [Expand chart above](/assets/typegraphs/SetHash.svg)
  