class Mix does Mixy { }

A Mix is an immutable collection of distinct elements in no particular order that each have a real-number weight assigned to them. (For mutable mixes, see MixHash instead.)

Mixes are often used for performing weighted random selections - see .roll.

Objects/values of any type are allowed as mix elements. Within a Mix, 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).Mix;

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␤»

Mixes can be treated as object hashes using the { } postcircumfix operator, or the < > postcircumfix operator 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:

my $recipe = (butter => 0.22, sugar => 0.1,
              flour => 0.275, sugar => 0.02).Mix;
say $recipe<butter>;     # OUTPUT: «0.22␤»
say $recipe<sugar>;      # OUTPUT: «0.12␤»
say $recipe<chocolate>;  # OUTPUT: «0␤»

Creating Mix objects§

Mixes can be composed using the mix subroutine (or Mix.new, for which it is a shorthand). 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 = mix "a", "a", "b" => 0, 3.14, π, π; # The Pair is a single element
say $n.keys.map: *.^name; # OUTPUT: «(Rat Pair Num Str)␤»
say $n.pairs;
# OUTPUT: «(3.14 => 1 (b => 0) => 1 3.141592653589793 => 2 a => 2)␤»

Alternatively, the .Mix coercer (or its functional form, Mix()) can be called on an existing object to coerce it to a Mix. 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).Mix;
say $n.keys.map(&WHAT);  # OUTPUT: «((Str) (Str))␤»
say $n.pairs;            # OUTPUT: «(a => 2 c => 3.14)␤»

Elements with a 0 value, as b above, are simply eliminated from the Mix.

Alternatively, since Mixes are Associative, we can use the % sigil to declare them; in that case, we can employ is to declare their type:

my %n is Mix = ("a", "a", "b" => 0, "c" => 3.14);
say %n.^name; # OUTPUT: «Mix␤»
say %n;       # OUTPUT: «Mix(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 Mix. This can either be done when calling .new:

# only allow strings
my $n = Mix[Str].new: <a b b c c c>;

or using the masquerading syntax:

# only allow strings
my %m is Mix[Str] = <a b b c c c>;
say %m<b>;  # OUTPUT: «2␤»
say %m<d>;  # OUTPUT: «0␤»

# only allow whole numbers
my %m is Mix[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, Mix.

Examples:

my $this-mix = (sugar =>, spice => ¼, all-things-nice => ¾);
my $that-mix = ( sugar => 1, spice => 2);

say $that-mix (<) $this-mix;     # OUTPUT: «True␤»
say $that-mix (^) $this-mix;     # OUTPUT: «Set(all-things-nice)␤»
say $that-mix (+) $this-mix;     # OUTPUT: «Bag(spice(2) sugar)␤»

# Unicode versions:
say $that-mix  $this-mix;     # OUTPUT: «True␤»
say $that-mix  $this-mix;     # OUTPUT: «Set(all-things-nice)␤»
say $that-mix  $this-mix;     # OUTPUT: «Bag(spice(2) sugar)␤»

sub mix§

sub mix(*@args --> Mix)

Creates a new Mix from @args.

Methods§

method Bag§

method Bag (--> Bag:D)

Coerces the Mix to a Bag. The weights are convert to Int, which means the number of keys in the resulting Bag can be fewer than in the original Mix, if any of the weights are negative or truncate to zero.

method BagHash§

method BagHash (--> BagHash:D)

Coerces the Mix to a BagHash. The weights are convert to Int, which means the number of keys in the resulting BagHash can be fewer than in the original Mix, if any of the weights are negative or truncate to zero.

method reverse§

Note: This method is inherited from Any, however, Mixes do not have an inherent order and you should not trust it returning a consistent output.

method total§

method total(Mix:D: --> Real)

Returns the sum of all the weights

say mix('a', 'b', 'c', 'a', 'a', 'd').total == 6;  # OUTPUT: «True␤»
say %(a => 5.6, b => 2.4).Mix.total == 8;          # OUTPUT: «True␤»

Note on order§

Same as the other elements in the Bag/Mix suite, order is not guaranteed or consistent and you shouldn't rely on methods like reverse above returning always the same result.

See Also§

Sets, Bags, and Mixes

Typegraph§

Type relations for Mix
raku-type-graph Mix Mix Any Any Mix->Any Mixy Mixy Mix->Mixy Mu Mu Any->Mu Associative Associative QuantHash QuantHash QuantHash->Associative Baggy Baggy Baggy->QuantHash Mixy->Baggy

Expand chart above