txt: ## baggy.md
  role Baggy
  
  Collection of distinct weighted objects
  
  ```raku
  role Baggy does QuantHash { }
  ```
  
  A role for collections of weighted objects. See [`Bag`](/type/Bag), [`BagHash`](/type/BagHash), and [`Mixy`](/type/Mixy).
  
  # [Methods](#role_Baggy "go to top of document")[§](#Methods "direct link")
  
  ## [method new-from-pairs](#role_Baggy "go to top of document")[§](#method_new-from-pairs "direct link")
  
  ```raku
  method new-from-pairs(Baggy: *@pairs --> Baggy:D)
  ```
  
  Constructs a Baggy objects from a list of [`Pair`](/type/Pair) objects given as positional arguments:
  
  ```raku
  say Mix.new-from-pairs: 'butter' => 0.22, 'sugar' => 0.1, 'sugar' => 0.02;
  # OUTPUT: «Mix(butter(0.22) sugar(0.12))␤»
  ```
  
  **Note:** be sure you aren't accidentally passing the Pairs as positional arguments; the quotes around the keys in the above example are significant.
  
  ## [method grab](#role_Baggy "go to top of document")[§](#method_grab "direct link")
  
  ```raku
  multi method grab(Baggy:D: --> Any)
  multi method grab(Baggy:D: $count --> Seq:D)
  ```
  
  Like [pick](#method_pick), a `grab` returns a random selection of elements, weighted by the values corresponding to each key. Unlike `pick`, it works only on mutable structures, e.g. [`BagHash`](/type/BagHash). Use of `grab` on an immutable structure results in an [`X::Immutable`](/type/X/Immutable) exception. If `*` is passed as `$count`, or `$count` is greater than or equal to the [total](#method_total) of the invocant, then `total` elements from the invocant are returned in a random sequence; i.e. they are returned shuffled.
  
  Grabbing decrements the grabbed key's weight by one (deleting the key when it reaches 0). By definition, the `total` of the invocant also decreases by one, so the probabilities stay consistent through subsequent `grab` operations.
  
  ```raku
  my $cars = ('Ford' => 2, 'Rover' => 3).BagHash;
  say $cars.grab;                                   # OUTPUT: «Ford␤»
  say $cars.grab(2);                                # OUTPUT: «(Rover Rover)␤»
  say $cars.grab(*);                                # OUTPUT: «(Rover Ford)␤»
  
  my $breakfast = ('eggs' => 2, 'bacon' => 3).Bag;
  say $breakfast.grab;
  CATCH { default { put .^name, ': ', .Str } };
  # OUTPUT: «X::Immutable: Cannot call 'grab' on an immutable 'Bag'␤»
  ```
  
  ## [method grabpairs](#role_Baggy "go to top of document")[§](#method_grabpairs "direct link")
  
  ```raku
  multi method grabpairs(Baggy:D: --> Any)
  multi method grabpairs(Baggy:D: $count --> Seq:D)
  ```
  
  Returns a [`Pair`](/type/Pair) or a [`Seq`](/type/Seq) of [`Pair`](/type/Pair)s depending on the version of the method being invoked. Each [`Pair`](/type/Pair) returned has an element of the invocant as its key and the element's weight as its value. Unlike [pickpairs](/routine/pickpairs), it works only on mutable structures, e.g. [`BagHash`](/type/BagHash). Use of `grabpairs` on an immutable structure results in an `X::Immutable` exception. If `*` is passed as `$count`, or `$count` is greater than or equal to the number of [elements](#method_elems) of the invocant, then all element/weight [`Pair`](/type/Pair)s from the invocant are returned in a random sequence.
  
  What makes `grabpairs` different from [pickpairs](#method_pickpairs) is that the 'grabbed' elements are in fact removed from the invocant.
  
  ```raku
  my $breakfast = (eggs => 2, bacon => 3).BagHash;
  say $breakfast.grabpairs;                         # OUTPUT: «bacon => 3␤»
  say $breakfast;                                   # OUTPUT: «BagHash.new(eggs(2))␤»
  say $breakfast.grabpairs(1);                      # OUTPUT: «(eggs => 2)␤»
  say $breakfast.grabpairs(*);                      # OUTPUT: «()␤»
  
  my $diet = ('eggs' => 2, 'bacon' => 3).Bag;
  say $diet.grabpairs;
  CATCH { default { put .^name, ': ', .Str } };
  # OUTPUT: «X::Immutable: Cannot call 'grabpairs' on an immutable 'Bag'␤»
  ```
  
  ## [method pick](#role_Baggy "go to top of document")[§](#method_pick "direct link")
  
  ```raku
  multi method pick(Baggy:D: --> Any)
  multi method pick(Baggy:D: $count --> Seq:D)
  ```
  
  Like an ordinary list [pick](/type/List#routine_pick), but returns keys of the invocant weighted by their values, as if the keys were replicated the number of times indicated by the corresponding value and then list pick used. The underlying metaphor for picking is that you're pulling colored marbles out a bag. (For "picking with replacement" see [roll](#method_roll) instead). If `*` is passed as `$count`, or `$count` is greater than or equal to the [total](#method_total) of the invocant, then `total` elements from the invocant are returned in a random sequence.
  
  Note that each `pick` invocation maintains its own private state and has no effect on subsequent `pick` invocations.
  
  ```raku
  my $breakfast = bag <eggs bacon bacon bacon>;
  say $breakfast.pick;                              # OUTPUT: «eggs␤»
  say $breakfast.pick(2);                           # OUTPUT: «(eggs bacon)␤»
  
  say $breakfast.total;                             # OUTPUT: «4␤»
  say $breakfast.pick(*);                           # OUTPUT: «(bacon bacon bacon eggs)␤»
  ```
  
  ## [method pickpairs](#role_Baggy "go to top of document")[§](#method_pickpairs "direct link")
  
  ```raku
  multi method pickpairs(Baggy:D: --> Pair:D)
  multi method pickpairs(Baggy:D: $count --> Seq:D)
  ```
  
  Returns a [`Pair`](/type/Pair) or a [`Seq`](/type/Seq) of [`Pair`](/type/Pair)s depending on the version of the method being invoked. Each [`Pair`](/type/Pair) returned has an element of the invocant as its key and the element's weight as its value. The elements are 'picked' without replacement. If `*` is passed as `$count`, or `$count` is greater than or equal to the number of [elements](#method_elems) of the invocant, then all element/weight [`Pair`](/type/Pair)s from the invocant are returned in a random sequence.
  
  Note that each `pickpairs` invocation maintains its own private state and has no effect on subsequent `pickpairs` invocations.
  
  ```raku
  my $breakfast = bag <eggs bacon bacon bacon>;
  say $breakfast.pickpairs;                         # OUTPUT: «eggs => 1␤»
  say $breakfast.pickpairs(1);                      # OUTPUT: «(bacon => 3)␤»
  say $breakfast.pickpairs(*);                      # OUTPUT: «(eggs => 1 bacon => 3)␤»
  ```
  
  ## [method roll](#role_Baggy "go to top of document")[§](#method_roll "direct link")
  
  ```raku
  multi method roll(Baggy:D: --> Any:D)
  multi method roll(Baggy:D: $count --> Seq:D)
  ```
  
  Like an ordinary list [roll](/type/List#routine_roll), but returns keys of the invocant weighted by their values, as if the keys were replicated the number of times indicated by the corresponding value and then list roll used. The underlying metaphor for rolling is that you're throwing `$count` dice that are independent of each other, which (in bag terms) is equivalent to picking a colored marble out your bag and then putting it back, and doing this `$count` times. In dice terms, the number of marbles corresponds to the number of sides, and the number of marbles of the same color corresponds to the number of sides with the same color. (For "picking without replacement" see [pick](#method_pick) instead).
  
  If `*` is passed to `$count`, returns a lazy, infinite sequence of randomly chosen elements from the invocant.
  
  ```raku
  my $breakfast = bag <eggs bacon bacon bacon>;
  say $breakfast.roll;                                  # OUTPUT: «bacon␤»
  say $breakfast.roll(3);                               # OUTPUT: «(bacon eggs bacon)␤»
  
  my $random_dishes := $breakfast.roll(*);
  say $random_dishes[^5];                               # OUTPUT: «(bacon eggs bacon bacon bacon)␤»
  ```
  
  ## [method pairs](#role_Baggy "go to top of document")[§](#method_pairs "direct link")
  
  ```raku
  method pairs(Baggy:D: --> Seq:D)
  ```
  
  Returns all elements and their respective weights as a [`Seq`](/type/Seq) of [`Pair`](/type/Pair)s where the key is the element itself and the value is the weight of that element.
  
  ```raku
  my $breakfast = bag <bacon eggs bacon>;
  my $seq = $breakfast.pairs;
  say $seq.sort;                                    # OUTPUT: «(bacon => 2 eggs => 1)␤»
  ```
  
  ## [method antipairs](#role_Baggy "go to top of document")[§](#method_antipairs "direct link")
  
  ```raku
  method antipairs(Baggy:D: --> Seq:D)
  ```
  
  Returns all elements and their respective weights as a [`Seq`](/type/Seq) of [`Pair`](/type/Pair)s, where the element itself is the value and the weight of that element is the key, i.e. the opposite of method [pairs](#method_pairs).
  
  ```raku
  my $breakfast = bag <bacon eggs bacon>;
  my $seq = $breakfast.antipairs;
  say $seq.sort;                                    # OUTPUT: «(1 => eggs 2 => bacon)␤»
  ```
  
  ## [method invert](#role_Baggy "go to top of document")[§](#method_invert "direct link")
  
  ```raku
  method invert(Baggy:D: --> Seq:D)
  ```
  
  Returns all elements and their respective weights as a [`Seq`](/type/Seq) of [`Pair`](/type/Pair)s, where the element itself is the value and the weight of that element is the key, i.e. the opposite of method [pairs](#method_pairs). Except for some esoteric cases, `invert` on a Baggy type returns the same result as [antipairs](#method_antipairs).
  
  ```raku
  my $breakfast = bag <bacon eggs bacon>;
  my $seq = $breakfast.invert;
  say $seq.sort;                                    # OUTPUT: «(1 => eggs 2 => bacon)␤»
  ```
  
  ## [method classify-list](#role_Baggy "go to top of document")[§](#method_classify-list "direct link")
  
  ```raku
  multi method classify-list(&mapper, *@list --> Baggy:D)
  multi method classify-list(%mapper, *@list --> Baggy:D)
  multi method classify-list(@mapper, *@list --> Baggy:D)
  ```
  
  Populates a *mutable* `Baggy` by classifying the possibly-empty `@list` of values using the given `mapper`. The `@list` cannot be lazy.
  
  ```raku
  say BagHash.new.classify-list: { $_ %% 2 ?? 'even' !! 'odd' }, ^10;
  # OUTPUT: BagHash(even(5) odd(5))
  
  my @mapper = <zero one two three four five>;
  say MixHash.new.classify-list: @mapper, 1, 2, 3, 4, 4, 6;
  # OUTPUT: MixHash((Any) two three four(2) one)
  ```
  
  The mapper can be a [`Callable`](/type/Callable) that takes a single argument, an [`Associative`](/type/Associative), or an [`Iterable`](/type/Iterable). With [`Associative`](/type/Associative) and an [`Iterable`](/type/Iterable) mappers, the values in the `@list` represent the key and index of the mapper's value respectively. A [`Callable`](/type/Callable) mapper will be executed once per each item in the `@list`, with that item as the argument and its return value will be used as the mapper's value.
  
  The mapper's value is used as the key of the `Baggy` that will be incremented by `1`. See [`.categorize-list`](/routine/categorize-list) if you wish to classify an item into multiple categories at once.
  
  **Note:** unlike the [`Hash`](/type/Hash)'s `.classify-list`, returning an [`Iterable`](/type/Iterable) mapper's value will throw, as `Baggy` types do not support nested classification. For the same reason, `Baggy`'s `.classify-list` does not accept `:&as` parameter.
  
  ## [method categorize-list](#role_Baggy "go to top of document")[§](#method_categorize-list "direct link")
  
  ```raku
  multi method categorize-list(&mapper, *@list --> Baggy:D)
  multi method categorize-list(%mapper, *@list --> Baggy:D)
  multi method categorize-list(@mapper, *@list --> Baggy:D)
  ```
  
  Populates a *mutable* `Baggy` by categorizing the possibly-empty `@list` of values using the given `mapper`. The `@list` cannot be lazy.
  
  ```raku
  say BagHash.new.categorize-list: {
      gather {
          take 'largish' if $_ > 5;
          take .is-prime ?? 'prime' !! 'non-prime';
          take $_ %% 2   ?? 'even'  !! 'odd';
      }
  }, ^10;
  # OUTPUT: BagHash(largish(4) even(5) non-prime(6) prime(4) odd(5))
  
  my %mapper = :sugar<sweet white>, :lemon<sour>, :cake('sweet', 'is-a-lie');
  say MixHash.new.categorize-list: %mapper, <sugar lemon cake>;
  # OUTPUT: MixHash(is-a-lie sour white sweet(2))
  ```
  
  The mapper can be a [`Callable`](/type/Callable) that takes a single argument, an [`Associative`](/type/Associative), or an [`Iterable`](/type/Iterable). With [`Associative`](/type/Associative) and an [`Iterable`](/type/Iterable) mappers, the values in the `@list` represent the key and index of the mapper's value respectively. A [`Callable`](/type/Callable) mapper will be executed once per each item in the `@list`, with that item as the argument and its return value will be used as the mapper's value.
  
  The mapper's value is used as a possibly-empty list of keys of the `Baggy` that will be incremented by `1`.
  
  **Note:** unlike the [`Hash`](/type/Hash)'s `.categorize-list`, returning a list of [`Iterables`](/type/Iterable) as mapper's value will throw, as `Baggy` types do not support nested categorization. For the same reason, `Baggy`'s `.categorize-list` does not accept `:&as` parameter.
  
  ## [method keys](#role_Baggy "go to top of document")[§](#method_keys "direct link")
  
  ```raku
  method keys(Baggy:D: --> Seq:D)
  ```
  
  Returns a [`Seq`](/type/Seq) of all keys in the `Baggy` object without taking their individual weights into account as opposed to [kxxv](#method_kxxv).
  
  ```raku
  my $breakfast = bag <eggs spam spam spam>;
  say $breakfast.keys.sort;                        # OUTPUT: «(eggs spam)␤»
  
  my $n = ("a" => 5, "b" => 2).BagHash;
  say $n.keys.sort;                                # OUTPUT: «(a b)␤»
  ```
  
  ## [method values](#role_Baggy "go to top of document")[§](#method_values "direct link")
  
  ```raku
  method values(Baggy:D: --> Seq:D)
  ```
  
  Returns a [`Seq`](/type/Seq) of all values, i.e. weights, in the `Baggy` object.
  
  ```raku
  my $breakfast = bag <eggs spam spam spam>;
  say $breakfast.values.sort;                      # OUTPUT: «(1 3)␤»
  
  my $n = ("a" => 5, "b" => 2, "a" => 1).BagHash;
  say $n.values.sort;                              # OUTPUT: «(2 6)␤»
  ```
  
  ## [method kv](#role_Baggy "go to top of document")[§](#method_kv "direct link")
  
  ```raku
  method kv(Baggy:D: --> Seq:D)
  ```
  
  Returns a [`Seq`](/type/Seq) of keys and values interleaved.
  
  ```raku
  my $breakfast = bag <eggs spam spam spam>;
  say $breakfast.kv;                                # OUTPUT: «(spam 3 eggs 1)␤»
  
  my $n = ("a" => 5, "b" => 2, "a" => 1).BagHash;
  say $n.kv;                                        # OUTPUT: «(a 6 b 2)␤»
  ```
  
  ## [method kxxv](#role_Baggy "go to top of document")[§](#method_kxxv "direct link")
  
  ```raku
  method kxxv(Baggy:D: --> Seq:D)
  ```
  
  Returns a [`Seq`](/type/Seq) of the keys of the invocant, with each key multiplied by its weight. Note that `kxxv` only works for `Baggy` types which have integer weights, i.e. [`Bag`](/type/Bag) and [`BagHash`](/type/BagHash).
  
  ```raku
  my $breakfast = bag <spam eggs spam spam bacon>;
  say $breakfast.kxxv.sort;                         # OUTPUT: «(bacon eggs spam spam spam)␤»
  
  my $n = ("a" => 0, "b" => 1, "b" => 2).BagHash;
  say $n.kxxv;                                      # OUTPUT: «(b b b)␤»
  ```
  
  ## [method elems](#role_Baggy "go to top of document")[§](#method_elems "direct link")
  
  ```raku
  method elems(Baggy:D: --> Int:D)
  ```
  
  Returns the number of elements in the `Baggy` object without taking the individual elements' weight into account.
  
  ```raku
  my $breakfast = bag <eggs spam spam spam>;
  say $breakfast.elems;                             # OUTPUT: «2␤»
  
  my $n = ("b" => 9.4, "b" => 2).MixHash;
  say $n.elems;                                     # OUTPUT: «1␤»
  ```
  
  ## [method total](#role_Baggy "go to top of document")[§](#method_total "direct link")
  
  ```raku
  method total(Baggy:D:)
  ```
  
  Returns the sum of weights for all elements in the `Baggy` object.
  
  ```raku
  my $breakfast = bag <eggs spam spam bacon>;
  say $breakfast.total;                             # OUTPUT: «4␤»
  
  my $n = ("a" => 5, "b" => 1, "b" => 2).BagHash;
  say $n.total;                                     # OUTPUT: «8␤»
  ```
  
  ## [method default](#role_Baggy "go to top of document")[§](#method_default "direct link")
  
  ```raku
  method default(Baggy:D: --> 0)
  ```
  
  Returns zero.
  
  ```raku
  my $breakfast = bag <eggs bacon>;
  say $breakfast.default;                           # OUTPUT: «0␤»
  ```
  
  ## [method hash](#role_Baggy "go to top of document")[§](#method_hash "direct link")
  
  ```raku
  method hash(Baggy:D: --> Hash:D)
  ```
  
  Returns a [`Hash`](/type/Hash) where the elements of the invocant are the keys and their respective weights the values.
  
  ```raku
  my $breakfast = bag <eggs bacon bacon>;
  my $h = $breakfast.hash;
  say $h.^name;                    # OUTPUT: «Hash[Any,Any]␤»
  say $h;                          # OUTPUT: «{bacon => 2, eggs => 1}␤»
  ```
  
  ## [method Bool](#role_Baggy "go to top of document")[§](#method_Bool "direct link")
  
  ```raku
  method Bool(Baggy:D: --> Bool:D)
  ```
  
  Returns `True` if the invocant contains at least one element.
  
  ```raku
  my $breakfast = ('eggs' => 1).BagHash;
  say $breakfast.Bool;                              # OUTPUT: «True␤»
                                                    # (since we have one element)
  $breakfast<eggs> = 0;                             # weight == 0 will lead to element removal
  say $breakfast.Bool;                              # OUTPUT: «False␤»
  ```
  
  ## [method Set](#role_Baggy "go to top of document")[§](#method_Set "direct link")
  
  ```raku
  method Set(--> Set:D)
  ```
  
  Returns a [`Set`](/type/Set) whose elements are the [keys](#method_keys) of the invocant.
  
  ```raku
  my $breakfast = (eggs => 2, bacon => 3).BagHash;
  say $breakfast.Set;                               # OUTPUT: «Set(bacon eggs)␤»
  ```
  
  ## [method SetHash](#role_Baggy "go to top of document")[§](#method_SetHash "direct link")
  
  ```raku
  method SetHash(--> SetHash:D)
  ```
  
  Returns a [`SetHash`](/type/SetHash) whose elements are the [keys](#method_keys) of the invocant.
  
  ```raku
  my $breakfast = (eggs => 2, bacon => 3).BagHash;
  my $sh = $breakfast.SetHash;
  say $sh.^name;                            # OUTPUT: «SetHash␤»
  say $sh.elems;                            # OUTPUT: «2␤»
  ```
  
  ## [method ACCEPTS](#role_Baggy "go to top of document")[§](#method_ACCEPTS "direct link")
  
  ```raku
  method ACCEPTS($other --> Bool:D)
  ```
  
  Used in smartmatching if the right-hand side is a `Baggy`.
  
  If the right-hand side is the type object, i.e. `Baggy`, the method returns `True` if `$other` [does](/type/Mu#routine_does) `Baggy` otherwise `False` is returned.
  
  If the right-hand side is a `Baggy` object, `True` is returned only if `$other` has the same elements, with the same weights, as the invocant.
  
  ```raku
  my $breakfast = bag <eggs bacon>;
  say $breakfast ~~ Baggy;                            # OUTPUT: «True␤»
  say $breakfast.does(Baggy);                         # OUTPUT: «True␤»
  
  my $second-breakfast = (eggs => 1, bacon => 1).Mix;
  say $breakfast ~~ $second-breakfast;                # OUTPUT: «True␤»
  
  my $third-breakfast = (eggs => 1, bacon => 2).Bag;
  say $second-breakfast ~~ $third-breakfast;          # OUTPUT: «False␤»
  ```
  
  # [See Also](#role_Baggy "go to top of document")[§](#See_Also "direct link")
  
  [Sets, Bags, and Mixes](/language/setbagmix)
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `Baggy`
  
  
  
  raku-type-graph
  
  
  
  Baggy
  Baggy
  
  
  QuantHash
  QuantHash
  
  
  Baggy->QuantHash
  
  
  
  Associative
  Associative
  
  
  QuantHash->Associative
  
  
  
  Mu
  Mu
  
  
  Any
  Any
  
  
  Any->Mu
  
  
  
  Bag
  Bag
  
  
  Bag->Baggy
  
  
  
  Bag->Any
  
  
  
  BagHash
  BagHash
  
  
  BagHash->Baggy
  
  
  
  BagHash->Any
  
  
  
  Mixy
  Mixy
  
  
  Mixy->Baggy
  
  
  
  Mix
  Mix
  
  
  Mix->Any
  
  
  
  Mix->Mixy
  
  
  
  MixHash
  MixHash
  
  
  MixHash->Any
  
  
  
  MixHash->Mixy
  
  [Expand chart above](/assets/typegraphs/Baggy.svg)
  