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»
MixHash
es 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
MixHash
es 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.