=begin pod

=TITLE class MixHash

=SUBTITLE Mutable collection of distinct objects with Real weights

    class MixHash does Mixy { }

A C<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
I<immutable> mixes, see L<Mix> instead.)

Objects/values of any type are allowed as mix elements. Within a C<MixHash>,
items that would compare positively with the L<===> operator are considered the
same element, with a combined weight.

=begin code
my $recipe = (butter => 0.22, sugar => 0.1,
              flour => 0.275, sugar => 0.02).MixHash

say $recipe.elems;      # 3
say $recipe.keys.sort;  # butter flour sugar
say $recipe.pairs.sort; # "butter" => 0.22 "flour" => 0.275 "sugar" => 0.12
say $recipe.total;      # 0.615
=end code

C<MixHash>es can be treated as object hashes using the C<{ }> postcircumfix
operator, which returns the corresponding numeric weight for keys that are
elements of the mix, and C<0> for keys that aren't. It can also be used to modify
weights; Setting a weight to C<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:

=begin code
say $recipe<butter>;     # 0.22
say $recipe<sugar>;      # 0.12
say $recipe<chocolate>;  # 0

$recipe<butter> = 0;
$recipe<chocolate> = 0.30;
say $recipe.pairs;       # "sugar" => 0.12 "flour" => 0.275 "chocolate" => 0.3
=end code


=head1 Creating C<MixHash> objects

C<MixHash>es can be composed using C<MixHash.new>. Any positional parameters,
regardless of their type, become elements of the mix - with a weight of C<1> for
each time the parameter occurred:

    my $n = MixHash.new: "a", "a", "b" => 0, "c" => 3.14;
    say $n.keys.map(&WHAT);  # (Str) (Pair) (Pair)
    say $n.pairs;            # "a" => 2 ("b" => 0) => 1 ("c" => 3.14) => 1

Alternatively, the C<.MixHash> coercer (or its functional form, C<MixHash()>)
can be called on an existing object to coerce it to a C<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);  # (Str) (Str)
    say $n.pairs;            # "a" => 2 "c" => 3.14

=head1 Operators

=begin comment

TODO: Expand this section (using the corresponding section in
lib/Type/BagHash.pod as a guide) after ab5tract's set/bag/mix operator redesign.

=end comment

See L<setbagmix#Set/Bag Operators> for a complete list of set and bag operators
with detailed explanations.

=head1 See Also

L<Sets, Bags, and Mixes|/language/setbagmix>

=end pod
