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.)
Mix
es 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»
Mix
es 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§
Mix
es 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 Mix
es 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, Mix
es 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.