class MixHash

Mutable collection of distinct objects with Real weights
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.

See Also

Sets, Bags, and Mixes

See Also

class Array

Sequence of itemized values

class Bag

Immutable collection of distinct objects with integer weights

class BagHash

Mutable collection of distinct objects with integer weights

class Capture

Argument list suitable for passing to a Signature

class Hash

Mapping from strings to itemized values

class IterationBuffer

Low level storage of positional values

class List

Sequence of values

class Map

Immutable mapping from strings to values

class Mix

Immutable collection of distinct objects with Real weights

class NFC

Codepoint string in Normal Form C (composed)

class NFD

Codepoint string in Normal Form D (decomposed)

class NFKC

Codepoint string in Normal Form KC (compatibility composed)

class NFKD

Codepoint string in Normal Form KD (compatibility decomposed)

class Pair

Key/value pair

class PseudoStash

Stash type for pseudo-packages

class Range

Interval of ordered values

class Seq

An iterable, potentially lazy sequence of values

class Set

Immutable collection of distinct objects

class SetHash

Mutable collection of distinct objects

class Slip

A kind of List that automatically flattens into an outer container

class Stash

Table for "our"-scoped symbols

class Uni

A string of Unicode codepoints

class utf8

Mutable uint8 buffer for utf8 binary data

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.