=encoding utf8 =head1 TITLE DRAFT: Synopsis 32: Setting Library - Containers.pod =head1 AUTHORS Rod Adams Larry Wall Aaron Sherman Mark Stosberg Carl Mäsak Moritz Lenz Tim Nelson =head1 VERSION Created: 19 Feb 2009 extracted from S29-functions.pod Last Modified: 20 Aug 2010 Version: 19 The document is a draft. If you read the HTML version, it is generated from the Pod in the pugs repository under /docs/Perl6/Spec/S32-setting-library/Containers.pod so edit it there in the SVN repository if you would like to make changes. =head1 Function Roles =head2 Positional role Positional {...} The C role implies the ability to support C<< postcircumfix:<[ ]> >>. =head2 Associative role Associative {...} The C role implies the ability to support C<< postcircumfix:<{ }> >>. =head2 Container role Container {...} =over =item cat our Cat multi cat( **@list ) C reads arrays serially rather than in parallel as C does. It returns all of the elements of the containers that were passed to it like so: cat(@a;@b;@c); Typically, you could just write C<(@a,@b,@c)>, but sometimes it's nice to be explicit about that: @foo := [[1,2,3],[4,5,6]]; say cat(||@foo); # 1,2,3,4,5,6 In addition, a C in item context emulates the C interface lazily. [Conjecture: Cats should maybe just do the lazy strings, and leave flattening to other operators.] =item roundrobin our Parcel multi roundrobin( **@list ) C is very similar to C. The difference is that C will not stop on lists that run out of elements but simply skip any undefined value: my @a = 1; my @b = 1..2; my @c = 1..3; for roundrobin( @a; @b; @c ) -> $x { ... } will get the following values for C<$x>: C<1, 1, 1, 2, 2, 3> =item zip our Parcel of Parcel multi zip ( **@list ) our Parcel of Parcel multi infix: ( **@list ) zip takes any number of arrays and returns one tuple for every index. This is easier to read in an example: for zip(@a;@b;@c) -> $nth_a, $nth_b, $nth_c { ... } Mnemonic: the input arrays are "zipped" up like a zipper. The C function defaults to stopping as soon as any of its lists is exhausted. This behavior may be modified by conceptually extending any short list using C<*>, which replicates the final element. If all lists are potentially infinite, an evaluation in C context will automatically fail as soon as it can be known that all sublists in the control of iterators of infinite extent, such as indefinite ranges or arbitrary replication. If it can be known at compile time, a compile-time error results. C is an infix equivalent for zip: for @a Z @b Z @c -> $a, $b, $c {...} In slice context a list of C is returned instead of a flat list. =back =head2 List The following are defined in the C role/class: role List does Container {...} =over =item new our List multi method new(*@args) Constructs an C that can visit all iterable elements of the all the arguments. =item list our List sub list(*@args) Constructs an C that can visit all iterable elements of the all the arguments. =item cat our Cat multi cat ( @values ) Returns a C object, a concatenated version of the list that does the C interface, but generates the string lazily to the extent permitted by the pattern of access to the string. Its two primary uses are matching against an array of strings and doing the equivalent of a C, except that C is always eager. However, a C in an interpolative context is also effectively eager, since the interpolator needs to know the string length. List context is lazy, though, so a C of a C is also lazy, and in fact, you just get a flat cat because C in a list context is a no-op. The C interface also lets you interrogate the object at a particular string position without actually stringifying the element; the regex engine can make use of this to match a tree node, for instance, without serializing the entire subtree. Accessing a filehandle as both a filehandle and as a C is undefined, because lazy objects are not required to be as lazy as possible, but may instead choose to precalculate values in semi-eager batches to maximize cache hits. =item classify our List of Pair multi method classify ( @values: Matcher $test ) our List of Pair multi classify ( Matcher $test, *@values ) C takes a list or array of values and returns a lazily evaluated list comprised of pairs whose values are arrays of values from the input list, and whose keys are the return value of the C<$test>, when passed that value. For example: @list = (1, 2, 3, 4); (:@even, :@odd) := classify { $_ % 2 ?? 'odd' !! 'even' }, @list; In this example, @even will contain all even numbers from C<@list> and C<@odd> will contain all odd numbers from C<@list>. To simply transform a list into a hash of arrays: %cars_by_color = classify { .color }, @cars; red_car_owners(%cars_by_color.map:{.owner}); =item grep our List multi method grep ( @values: Matcher $test ) our List multi grep ( Matcher $test, *@values ) C takes a list or array of values and returns a lazily evaluated list comprised of all of the values from the original list for which the C<$test> smart-matches as true. Here is an example of its use: @friends = grep { .is_friend }, @coworkers; This takes the array C<@coworkers>, checks every element to see which ones return true for the C<.is_friend> method, and returns the resulting list to store into C<@friends>. Note that, unlike in Perl 5, a comma is required after the C in the multi form. =item first our Parcel multi method first ( @values: Matcher $test ) our Parcel multi first ( Matcher $test, *@values ) C searches exactly like C but returns only the first matching value. =item pick our multi method pick ( @values: Int $num = 1, Bool :$replace ) our multi method pick ( @values: Whatever, Bool :$replace ) our multi pick ( Int $num, Bool :$replace, *@values ) our multi pick ( Whatever, Bool :$replace, *@values ) C takes a list or array of values and returns a random selection of elements from the list (without replacement unless C<:replace> is indicated). When selecting without replacement if C<*> is specified as the number (or if the number of elements in the list is less than the specified number), all the available elements are returned in random order: @team = @volunteers.pick(5); @shuffled = @deck.pick(*); When selecting with replacement the specified number of picks are provided. In this case C<*> would provide an infinite list of random picks from C<@values>: @byte = (0,1).pick(8, :replace); for (1..20).pick(*, :replace) -> $die_roll { ... } Due to the normal semantics of returning a C, a pick of a single element may be used as an item without requiring C<.[0]>. =item join our Str multi method join ( @values: Str $separator = '' ) our Str multi join ( Str $separator = '', *@values ) C returns a single string comprised of all of the elements of C<@values>, separated by C<$separator>. Given an empty list, C returns the empty string. The separator defaults to the null string. To join with space, just coerce to C. =item map our List of Parcel multi method map ( @values: Code *&expression ) our List of Parcel multi map ( Code $expression, *@values ) C returns a lazily evaluated list which is comprised of the return value of the expression, evaluated once for every one of the C<@values> that are passed in. If the expression returns no values or multiple values, then the resulting list may not be the same length as the number of values that were passed. The actual return value is a multislice containing one slice per map iteration. In most contexts these slices are flattened into a single list. =item reduce our Item multi method reduce ( @values: Code *&expression ) our Item multi reduce ( Code $expression ;; *@values ) { my $res; for @values -> $cur { FIRST {$res = $cur; next;} $res = &$expression($res, $cur); } $res; } =item reverse our List multi method reverse ( @values: ) is export our List multi reverse ( *@values ) { gather { 1 while take pop @values; } } Note that strings are now reversed with C. =item rotate our List multi method rotate ( @values is copy: Int $n = 1) is export Produces a new list with the same elements as the old list, rotated by the specified amount. See Array::rotate for more info. =item sort our Array multi method sort( @values: *&by ) our Array multi method sort( @values: Ordering @by ) our Array multi method sort( @values: Ordering $by = &infix: ) our List multi sort( Ordering @by, *@values ) our List multi sort( Ordering $by, *@values ) Returns C<@values> sorted, using criteria C<$by> or C<@by> for comparisons. C<@by> differs from C<$by> in that each criterion is applied, in order, until a non-zero (tie) result is achieved. If C<$by> is a code object of arity zero or one, it is applied on each item of C<@values>, and C<@values> is sorted by comparing the result values with C<< &infix: >> (Schwartzian Transform). C is as described in L<"Type Declarations">. Any C may receive either or both of the mixins C and C to reverse the order of sort, or to adjust the case, sign, or other order sensitivity of C. (Mixins are applied to values using C.) If a C is used as an C then sort-specific traits such as C are allowed on the positional elements. If all criteria are exhausted when comparing two elements, sort should return them in the same relative order they had in C<@values>. To sort an array in place use the C<.=sort> mutator form. See L for more details and examples (with C meaning C.) =item min our multi method min( @values: *&by ) our multi method min( @values: Ordering @by ) our multi method min( @values: Ordering $by = &infix: ) our multi min( *@values, Ordering :@by ) our multi min( *@values, Ordering :$by ) Returns the earliest (i.e., lowest index) minimum element of C<@values> , using criteria C<$by> or C<@by> for comparisons. C<@by> differs from C<$by> in that each criterion is applied, in order, until a non-zero (tie) result is achieved. C is as described in L<"Type Declarations">. Any C may receive the mixin C to adjust the case, sign, or other order sensitivity of C. (Mixins are applied to values using C.) If a C is used as an C then sort-specific traits such as C are allowed on the positional elements. For a C function that does not require an ordering, see the C<[min]> reduction operator. =item max our multi method max( @values: *&by ) our multi method max( @values: Ordering @by ) our multi method max( @values: Ordering $by = &infix: ) our multi max(*@values, Ordering :@by,) our multi max(*@values, Ordering :$by,) Returns the earliest (i.e., lowest index) maximum element of C<@values> , using criteria C<$by> or C<@by> for comparisons. C<@by> differs from C<$by> in that each criterion is applied, in order, until a non-zero (tie) result is achieved. C is as described in L<"Type Declarations">. Any C may receive the mixin C to adjust the case, sign, or other order sensitivity of C. (Mixins are applied to values using C.) If a C is used as an C then sort-specific traits such as C are allowed on the positional elements. For a C function that does not require an ordering, see the C<[max]> reduction operator. =item minmax our multi method minmax( @values: *&by ) our multi method minmax( @values: Ordering @by ) our multi method minmax( @values: Ordering $by = &infix: ) our multi minmax( *@values, Ordering :@by ) our multi minmax( *@values, Ordering :$by ) Returns a C from the minimum element of C<@values> to the maximum element, using criteria C<$by> or C<@by> for comparisons. C<@by> differs from C<$by> in that each criterion is applied, in order, until a non-zero (tie) result is achieved. C elements in C<@values> are treated as if their minimum and maximum values were passed individually, except that if the corresponding C flag is set in Range, the excludes flag is also set in the returned C. C is as described in L<"Type Declarations">. Any C may receive the mixin C to adjust the case, sign, or other order sensitivity of C. (Mixins are applied to values using C.) If a C is used as an C then sort-specific traits such as C are allowed on the positional elements. For a C function that does not require an ordering, see the C<[minmax]> reduction operator. =item any our Junction multi method any( @values: ) our Junction multi any( *@values ) is export Returns a junction with all the values of the list C<|>-ed together. The junction will only match against another value if at least one of the values in the list matches. =item all our Junction multi method all( @values: ) our Junction multi all( *@values ) is export Returns a junction with all the values of the list C<&>-ed together. The junction will only match against another value if all of the values in the list match. =item one our Junction multi method one( @values: ) our Junction multi one( *@values ) is export Returns a junction with all the values of the list C<^>-ed together. The junction will only match against another value if exactly one of the values in the list matches. =item none our Junction multi method none( @values: ) our Junction multi none( *@values ) is export Returns a junction which will only match against another value if none of the values in the list matches. =item comb multi method comb ( Regex $matcher, Int $limit = * ) Treats the list as a string (by simply Cing them together), and calls C<.comb> on that string with the same parameters. See C. =back =head2 Array All these methods are defined in the C role/class. role Array does List {...} =over =item new our Array multi method new(*@args) Constructs a new C containing the arguments passed to C. =item shape our Parcel method shape (@array: ) is export Returns the declared shape of the array, as described in S09. =item end our Any method end (@array: ) is export Returns the final subscript of the first dimension; for a one-dimensional array this simply the index of the final element. For fixed dimensions this is the declared maximum subscript. For non-fixed dimensions (undeclared or explicitly declared with C<*>), the index of the actual last element is used. =item elems our Int method elems (@array: ) is export Returns the length of the array counted in elements. =item delete our List method delete (@array : *@indices ) is export Sets elements specified by C<@indices> in the invocant to a non-existent state, as if they never had a value. Deleted elements at the end of an Array shorten the length of the Array, unless doing so would violate an C definition. The interpretation of C<@indices> is subject to change. The normal way to delete is by applying a C<:delete> adverb to any subscripting operation. Returns the value(s) previously held in deleted locations. =item :delete This adverb may be applied to any subscripting operation. The operation returns the elements normally, but reads them out destructively. =item exists our Bool method exists (@array : Int *@indices ) True if the specified Array element has been assigned to. This is not the same as being defined. Supplying a different number of indices than invocant has dimensions is an error. The normal way to test for existence is to apply the C<:exists> adverb to a subscripting operation. =item :exists This adverb may be applied to any subscripting operation. The operation returns true if specified element exists. If a slice is specified by the subscript, a C of C is returned, which can be processed using junctions. =item pop our Scalar multi method pop ( @array: ) is export Remove the last element of C<@array> and return it. If C<@array> is empty returns a failure. =item push our Array multi method push ( @array: *@values ) is export Adds all the values to the end of C<@array> eagerly. Returns the modified array. =item plan our Array multi method plan ( @array: *@list ) is export Adds the list to the end of C<@array> lazily as a kind of "lazy push". (That is, the reified part of the array is not modified, but the list is appended to the not-yet-reified specifications for how to extend the array on demand, if it is subscripted or shifted beyond the currently reified elements.) Returns the modified array. Note that the semantics of these are different: @ro := (0,1,*+*...*); @rw.plan(0,1,*+*...*); In the first case, C<@ro> is bound directly to the list, so its values are memoized but not considered mutable. In contrast, C<@rw> allows modification of any reified element; new elements are merely initialized to the fibonacci sequence. If you try to modify a non-reified element, the array will be reified to that point before the modification is attempted. For all external purposes, the array considers that its plan is part of the array. If you ask for C<.elems>, for instance, it will try to reify the entire array, which might take a long time in the case of infinite arrays (though a list may return C if it can determine this). Methods such as C<.splice> can refer to the rest of the list in the abstract, and need only reify those elements necessary to perform the operation in question. (Hence, there is no need for an C<.unplan> method, since the plan of an array may be thrown away by using C without the risk of memory exhaustion.) =item rotate our Array multi method rotate ( @array is copy: Int $n = 1, Int *@n) is export Produces a new array with the same elements as the old array, rotated by the specified amount. A positive rotation of 1 is defined as: @array.push(@array.shift); A negative shift of 1 is defined as: @array.unshift(@array.pop); If the magnitude of C<$n> is larger than the number of elements, the rotational semantics must be equivalent to doing: @array.rotate(sign($n)) for ^abs($n) The new array to be returned contains nothing but aliases for the old array's elements; however, you can use this to get any of three different semantic behaviors: @a.=rotate # @a is rotated in place @b = @a.rotate # @b contains copied elements of rotated @a @b := @a.rotate # @b contains aliased elements of rotated @a If additional rotations are specified via the slurpy, they are applied to subdimensions of multidimensional arrays. (To perform a flat rotation on a shaped array requires flattening to a list and rotating that instead.) =item shift our Scalar multi method shift ( @array: ) is export Remove the first element from C<@array> and return it. If C<@array> is empty returns a failure. =item splice our multi method splice( @array is rw: Int $offset = 0, Int $size?, *@values ) is export C fills many niches in array-management, but its fundamental behavior is to remove zero or more elements from an array and replace them with a new (and potentially empty) list. This operation can shorten or lengthen the target array. C<$offset> is the index of the array element to start with. It defaults to C<0>. C<$size> is the number of elements to remove from C<@array>. It defaults to removing the rest of the array from C<$offset> on. The slurpy list of values (if any) is then inserted at C<$offset>. Calling splice with a traditional parameter list, you must define C<$offset> and C<$size> if you wish to pass a replacement list of values. To avoid having to pass these otherwise optional parameters, use the piping operator(s): splice(@array,10) <== 1..*; which replaces C<@array[10]> and all subsequent elements with an infinite series starting at C<1>. This behaves similarly to Perl 5's C. If C<@array> is multidimensional, C operates only on the first dimension, and works with Array References. C returns a C of the deleted elements, which behaves as expected in either list or item context. =item unshift our Array multi method unshift ( @array: *@values ) is export C adds the values onto the start of the C<@array> and returns the modified array. =item keys =item kv =item pairs =item values multi method keys ( @array: Matcher $indextest? ) is export multi method kv ( @array: Matcher $indextest? ) is export multi method pairs ( @array: Matcher $indextest? ) is export multi method enums ( @array: Matcher $indextest? ) is export multi method values ( @array: Matcher $indextest? ) is export Iterates the elements of C<@array>, in order. If C<$indextest> is provided, only elements whose indices match C<$index ~~ $indextest> are iterated. (To select on values use C.) What is returned at each element of the iteration varies with function. C returns the value of the associated element; C returns a 2 element list in (index, value) order, C a C. With C the values are references back to the original containers, while with C a snapshot of those values is taken. That is, C<.pairs> returns a C while C returns an C. If C<@array> is declared to be multi-dimensional, the keys returned may in fact be slice lists. (Arrays that are effectively multi-dimensional by containing other arrays or hashes are treat with their declared dimensionality, not their effective dimensionality.) Note that C returns the same as C =back =head2 Hash The following are defined in the C role. role Hash does Container does Associative {...} =over 4 =item :delete This adverb may be applied to any subscripting operation. The operation returns the elements normally, but reads them out destructively. =item :exists This adverb may be applied to any subscripting operation. The operation returns true if specified element exists. If a slice is specified by the subscript, a C of C is returned, which can be processed using junctions. =item keys =item kv =item pairs =item values multi method keys ( %hash: Matcher $keytest? ) is export multi method kv ( %hash: Matcher $keytest? ) is export multi method pairs ( %hash: Matcher $keytest? ) is export multi method enums ( %hash: Matcher $keytest? ) is export multi method values ( %hash: Matcher $keytest? ) is export Iterates the elements of C<%hash>. The order is implementation dependent and arbitrary, but will be the same between successive calls to these functions, as long as C<%hash> doesn't change. If C<$keytest> is provided, only elements whose keys evaluate C<$key ~~ $keytest> as true are iterated. What is returned at each element of the iteration varies with function. C only returns the key; C the value; C returns both as a 2 element list in (key, value) order, C a C. With C the values are references back to the original containers, while with C a snapshot of those values is taken. That is, C<.pairs> returns a C while C returns an C. Note that C returns the same as C The lvalue form of C is not longer supported. Use the C<.buckets> property instead. =item any our Junction multi method any( %hash: ) is export Returns a junction with all the keys of the hash C<|>-ed together. The junction will only match against another value if at least one of the keys in the hash matches. =item all our Junction multi method all( %hash: ) is export Returns a junction with all the keys of the hash C<&>-ed together. The junction will only match against another value if all of the keys in the hash match. =item one our Junction multi method one( %hash: ) is export Returns a junction with all the keys of the hash C<^>-ed together. The junction will only match against another value if exactly one of the keys in the hash matches. =item none our Junction multi method none( %hash: ) is export Returns a junction which will only match against another value if none of the keys in the hash matches. =item invert our List multi method invert ( %hash: ) is export { map -> $k, $v { $v X=> $k }, %hash.kv; } Produces a backmapping of values to keys, expanding list values into multiple pairs. (The C<< X=> >> expands C<$v> if it is a list.) [NB: this may need refinement to handle keys that do C.] =item push our Hash multi method push ( @hash: *@values ) is export Like hash assignment insofar as it accepts either C objects or alternating keys and values; also like in that it returns the new hash. However, unlike assignment, when a duplicate key is detected, C coerces the colliding entry's value to an array and pushes the C's value onto that array. Hence to invert a hash containing duplicate values without losing (associative) information, say: %out.push(%in.invert) Note that when reading the values of such a hash, you must not assume that all the elements are arrays, since the first instance of a key merely sets the value without turning it into an array. (Fortunately, most list operators create a list of one element when used on an object that is not a list.) The intent is that reversing a hash twice produces a hash equivalent to the original hash. =back =head1 Classes and Roles This documents Buf, List, Seq, Range, Set, Bag, Junction, Array, Hash, KeyHash, KeySet, KeyBag, Pair, and PairMap. =head2 Seq class Seq does Positional does Iterable {...} =head2 Range class Range does Positional does Iterable { method from() {...} method to() {...} method min() {...} method max() {...} method List minmax() {...} } =head2 Buf class Buf does Positional does Stringy {...} A mutable container for an array of integer values in contiguous memory. The default constructor takes a single array parameter of integers, the largest of which determines the actual type. So Buf.new([:16, :16]) # or Buf.new([195, 182]) # which is exactly the same returns a C containing two C items, while Buf.new([256]) returns a C which consists of a single C. To explicit request a C of a specific size, you can use Buf.new([127], :size(16)) # returns a buf16 Buf.new([1024], :size(8)) # dies, because 1024 >= 2**8 Subtypes with additional constraints like C (which only allows valid UTF-8 byte sequences) exist and provide similar constructors. See L. The array in the constructor used to be slurpy rather than positional, but the former was deemed to be too inefficient (during signature construction) for arrays of many elements. =head3 Methods =over =item decode our Str method decode($encoding = $?ENC, $nf = $?NF) Decode the C into a C. For subtypes that know their encoding (like C, C) the C<$encoding> parameter defaults to their intrinsic encoding instead. =back =head3 C Operators Two C objects of the same bit size can be compared with the same operators as strings (in particular C, C, C, C, C, C and C), but actually compares the stored integers, not characters. Concatenating two compatible Cs produces an object of the most specific type possible, for example C results in a C object. Comparing or concatenating two C objects of different bit sizes, or a C that doesn't know its encoding with a C throws an exception. Likewise, coercing an encoding-unaware C to C dies. [Conjecture: The behaviour of encoding-aware C objects on string operators is intentionally not defined yet, because I have no idea what implications on speed and usage they might have --moritz]. =head2 Enum and Pair class Enum does Associative {...} class Pair does Associative {...} A value formed by associating a single key with a single value. In an C, both key and value are immutable. In a C, the key is immutable but the value mutable. C works identically to C unless you try to modify it.) =over =item invert our List multi method invert ( $pair: ) is export { $pair.value X=> $pair.key } =back =head2 EnumMap class EnumMap does Associative does Positional {...} An immutable hash value, viewable either as a (constant) hash or as a sequence of Cs. The keys may not contain duplicates, while the values may. The implementation of C associativity is not guaranteed to be as efficient as a C lookup. (A brute force linear scan for the matching key is allowed. Optimization is also allowed.) =head2 PairMap class PairMap does Associative does Positional {...} A hash value that is mutable only in values, differing from a normal hash insofar as the key set is frozen. It may be accessed either as a frozen hash or as a sequence of Cs. The keys may not contain duplicates, while the values may. The implementation of C associativity is not guaranteed to be as efficient as a C lookup. (A brute force linear scan for the matching key is allowed. Optimization to something like an ordered hash is also allowed.) =head2 Set class Set does Associative {...} A set of unique values. When used as a hash always treats the set's values as the keys of the hash, returning C for set elements. See C for a container that can represent different sets as keys are added or deleted. A C responds to hash operators as if it were a C. =over =item pick our multi method pick ( $set: Int $num = 1, Bool :$replace ) our multi method pick ( $set: Whatever, Bool :$replace ) Works like an ordinary list C. =back =head2 KeySet A mutable Set container, represented as C. =head2 Bag class Bag does Associative {...} A collection of values that need not be unique, represented by an associative mapping from each key value to its replication number. The C<.elems> method returns the sum of all replication values. =over =item pick our multi method pick ( $bag: Int $num = 1, Bool :$replace ) our multi method pick ( $bag: Whatever, Bool :$replace ) our multi method pickpairs ( $bag: Int $num = 1, Bool :$replace ) our multi method pickpairs ( $bag: Whatever, Bool :$replace ) Like an ordinary list C, but returns keys of the bag weighted by values, as if the keys were replicated the number of times indicated by the corresponding value and then list pick used. C is the mutable form of C. A C responds to hash operators as if it were a C. The default metaphor for picking is that you're pulling colored marbles out a bag. Picking with replacement is easy to implement, since the weights never change, and the chance of getting any key is simply its replication value over C<.elems>. Other forms of picking require tracking the temporary state, so the immutable C is copied to a temporary private C, and the picks are made from that using the corresponding C<.grab> or C<.grabpairs> method (see below). Each C<.pick> invocation maintains its own private state and has no effect on subsequent C<.pick> invocations. =back =head2 KeyBag A mutable C container, represented as C. =head2 KeyHash role KeyHash[::T $t, $default = 0] does Associative {...} A C represents a mutable set of values, represented as the keys of a C. When asked to behave as a list it ignores its values and returns only C<.keys>. C and C are derived from this type, but constrain their values to be C and C, respectively. A C automatically deletes any key whose value goes false. For any C, the C<.elems> methods returns the current sum of the values, which the C must either track or compute on demand. Tracking is preferable for efficient implementation of C<.pick> and C<.grab>. All C containers have a default value that is false (such as C<0> or C<''> or C or C), and keep around only those entries with non-default values, deleting any entry if its value goes to false. =over =item grab our multi method grab ( $bag: Int $num = 1, Bool :$replace ) our multi method grab ( $bag: Whatever, Bool :$replace ) our multi method grabpairs ( $bag: Int $num = 1, Bool :$replace ) our multi method grabpairs ( $bag: Whatever, Bool :$replace ) Like C, a C returns a random selection of elements, weighted by the values corresponding to each key. Since a C, unlike a C or C, is mutable, C<.grab> works directly on the C, modifying it in place. (You may use C<.pick> to treat the C as immutable; this will copy it and grab only from the temporary copy.) Swiping without replacement (the default) decrements the grabbed key's replication value by one (deleting the key when it goes to 0). By definition, C<.elems> of the bag also decreases by one, so the probabilities stay consistent through subsequent grab operations. With the C<.grabpairs> version, the replication value of the picked key is forced immediately to 0, removing all marbles of that color from the bag, as it were. Instead of returning keys, returns the grabbed values as a list of C objects, whose keys are the deleted keys and whose values are the deleted replication values. =back =head2 KeyWeight A C; like a C but may have non-integral weights for use in weighted picking. Keys with fractional weights are deleted if they go to 0. Negative weights are not deleted, but the implementation may complain if it notices you attempting to use such a weight. =head2 Junction All method calls on junctions autothread because the type provides no public methods. =over 4 =item !eigenstates method !eigenstates (Junction $j: --> Parcel) Returns an unordered list of the values that constitute the junction (formerly called C<.values>). It flattens nested junctions of the same type, so C<(1|(2|3)).eigenstates> returns an arbitrary permutation of the list C<1, 2, 3>. Note this is a private method; you must arrange for yourself to be trusted by the junctions class in order to call it, which probably involves evil MONKEY_TYPING. Alternately, the values may be explicitly converted to a set value using C<.Set> or C. Note, however, that the set of eigenstates for a C junction defines the values that are *not* there, so the resulting C will be the I to the universe of values recognized by the junction! Also note that C and C junctions represent I of sets of items, not sets of items. Since set items are by definition unique, only the C junction can be unthinkingly mapped to and from a given set. (This is why we discourage casual use of the eigenstates as a set.) =back =head1 Additions Please post errors and feedback to perl6-language. If you are making a general laundry list, please separate messages by topic.