class MixHash
class MixHash does Mixy { }
A MixHash is a mutable mix, meaning a collection of distinct elements in no
particular order that each have a real-number weight assigned to them. (For
immutable mixes, see Mix instead.)
Objects/values of any type are allowed as mix elements. Within a MixHash,
items that would compare positively with the === operator are considered the
same element, with a combined weight.
my $recipe = (butter => 0.22, sugar => 0.1,
flour => 0.275, sugar => 0.02).MixHash;
say $recipe.elems; # OUTPUT: «3»
say $recipe.keys.sort; # OUTPUT: «butter flour sugar»
say $recipe.pairs.sort; # OUTPUT: «"butter" => 0.22 "flour" => 0.275 "sugar" => 0.12»
say $recipe.total; # OUTPUT: «0.615»
MixHashes can be treated as object hashes using the
{ } postcircumfix operator,
or the
< > postcircumfix operator|/language/operators#postcircumfix_<_>
for literal string keys, which
returns the corresponding numeric weight for keys that are
elements of the mix, and 0 for keys that aren't. It can also be used to modify
weights; Setting a weight to 0 automatically removes that element from the
mix, and setting a weight to a non-zero number adds that element if it didn't
already exist:
my $recipe = (butter => 0.22, sugar => 0.1,
flour => 0.275, sugar => 0.02).MixHash;
say $recipe<butter>; # OUTPUT: «0.22»
say $recipe<sugar>; # OUTPUT: «0.12»
say $recipe<chocolate>; # OUTPUT: «0»
$recipe<butter> = 0;
$recipe<chocolate> = 0.30;
say $recipe.pairs; # OUTPUT: «"sugar" => 0.12 "flour" => 0.275 "chocolate" => 0.3»
Creating MixHash objects
MixHashes can be composed using MixHash.new. Any positional parameters,
regardless of their type, become elements of the mix - with a weight of 1 for
each time the parameter occurred:
my $n = MixHash.new: "a", "a", "b" => 0, "c" => 3.14;
say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Pair) (Pair))»
say $n.pairs; # OUTPUT: «(a => 2 (c => 3.14) => 1 (b => 0) => 1)»
Alternatively, the .MixHash coercer (or its functional form, MixHash())
can be called on an existing object to coerce it to a MixHash. Its semantics
depend on the type and contents of the object. In general it evaluates the
object in list context and creates a mix with the resulting items as elements,
although for Hash-like objects or Pair items, only the keys become elements of
the mix, and the (cumulative) values become the associated numeric weights:
my $n = ("a", "a", "b" => 0, "c" => 3.14).MixHash;
say $n.keys.map(&WHAT); # OUTPUT: «((Str) (Str))»
say $n.pairs; # OUTPUT: «(a => 2 c => 3.14)»
Since 6.d (2019.03 and later) it is also possible to specify the type of values
you would like to allow in a MixHash. This can either be done when calling
.new:
# only allow strings
my $n = MixHash[Str].new: <a b b c c c>;
or using the masquerading syntax:
# only allow strings
my %mh is MixHash[Str] = <a b b c c c>;
say %mh<b>; # OUTPUT: «2»
say %mh<d>; # OUTPUT: «0»
# only allow whole numbers
my %mh is MixHash[Int] = <a b b c c 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, MixHash.
Examples:
my ($a, $b) = MixHash(2 => 2, 4), MixHash(2 => 1.5, 3 => 2, 4);
say $a (<) $b; # OUTPUT: «False»
say $a (<=) $b; # OUTPUT: «False»
say $a (^) $b; # OUTPUT: «MixHash(2(0.5) 3(2))»
say $a (+) $b; # OUTPUT: «MixHash(2(3.5) 4(2) 3(2))»
# Unicode versions:
say $a ⊂ $b; # OUTPUT: «False»
say $a ⊆ $b; # OUTPUT: «False»
say $a ⊖ $b; # OUTPUT: «MixHash(2(0.5) 3(2))»
say $a ⊎ $b; # OUTPUT: «MixHash(2(3.5) 4(2) 3(2))»
Note on reverse and ordering.
MixHash inherits reverse from Any,
however, Mixes do not have an inherent order and you should not trust
it returning a consistent output.
If you sort a MixHash, the result is a list of pairs, at which point
reverse makes perfect sense:
my $a = MixHash.new(2, 2, 18, 3, 4);
say $a; # OUTPUT: «MixHash(18 2(2) 3 4)»
say $a.sort; # OUTPUT: «(2 => 2 3 => 1 4 => 1 18 => 1)»
say $a.sort.reverse; # OUTPUT: «(18 => 1 4 => 1 3 => 1 2 => 2)»
Methods
method Bag
method Bag (--> Bag:D)
Coerces the MixHash to a Bag. The weights are converted
to Int,
which means the number of keys in the resulting Bag can be fewer than in the
original MixHash, if any of the weights are negative or truncate to zero.
method BagHash
method BagHash (--> BagHash:D)
Coerces the MixHash to a BagHash. The weights are converted
to Int,
which means the number of keys in the resulting BagHash can be fewer than in the
original MixHash, if any of the weights are negative or truncate to zero.