=encoding utf8 =head1 TITLE DRAFT: Synopsis 32: Setting Library - Containers.pod =head1 VERSION Created: 19 Feb 2009 extracted from S29-functions.pod Last Modified: 23 Apr 2015 Version: 51 =head1 Function Roles =head2 Positional role Positional {...} The C role implies the ability to support C<< postcircumfix:<[ ]> >>. =head2 Iterable role Iterable {...} The C role implies the ability to support sequential access through iterators. There is also limited support for en-passant use of C<< postcircumfix:<[ ]> >>, but since some Iterables may only be iterated once, not all Iterables are considered Positional. =head2 Associative role Associative {...} The C role implies the ability to support C<< postcircumfix:<{ }> >>. =over =item cat multi cat( **@list --> Cat ) 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 multi roundrobin( **@list --> Seq ) 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 multi zip ( **@list --> Seq ) multi infix: ( **@list --> Seq ) 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 lol context a list of C is returned instead of a flat list. =back =head2 List The following are defined in the C class: class List does Positional {...} =over =item new multi method new(*@args --> List ) Constructs an C that can visit all iterable elements of all the arguments. =item list sub list(*@args --> List ) Constructs a C that can visit all iterable elements of all the arguments. =item cat multi cat ( @values --> Cat ) 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 multi method classify ( @values: &mapper --> Hash ) multi method classify ( @values: %mapper --> Hash ) multi method classify ( @values: @mapper --> Hash ) multi classify ( &mapper, *@values --> Hash ) multi classify ( %mapper, *@values --> Hash ) multi classify ( @mapper, *@values --> Hash ) C transforms a finite list or array of values into a hash representing the classification of those values according to a mapper; each hash key represents the classification for one or more of the incoming list values, and the corresponding hash value contains an array of those list values classified by the mapper into the category of the associated key. For example: @list = (1, 2, 3, 4); (:@even, :@odd) := @list.classify: { $_ % 2 ?? 'odd' !! 'even' }; (:@even, :@odd) := classify { $_ % 2 ?? 'odd' !! 'even' }, @list; # same In this example, @even will contain all even numbers from C<@list> and C<@odd> will contain all odd numbers from C<@list>. Please note that for performance reasons, an implementation is free to C values to the resulting arrays. So you should consider these arrays to be immutable. To simply transform a list into a hash of arrays: %cars_by_color := @cars.classify: { .color }; %cars_by_color := classify { .color }, @cars; # same red_car_owners(%cars_by_color.map:{.owner}); A mapper may be any unary function, hash, or array. Values that have no mapping will be classified under an undefined failure key (whatever is returned by the mapper in use). [Conjecture: if a hash comes with a default value, it can map anything.] C always assumes that the mapper returns a single value. However, this may also be a L to indicate a multi-level classification. In such a case, only the classification of the lowest level, will actually yield a Hash of Lists. All higher up classifications, will necessarily always be a Hash of Hashes. Please note that all Lists must have the same number of elements. To categorize values into multiple categories, see C. =item categorize multi method categorize ( @values: &mapper --> Hash ) multi method categorize ( @values: %mapper --> Hash ) multi method categorize ( @values: @mapper --> Hash ) multi categorize ( &mapper, *@values --> Hash ) multi categorize ( %mapper, *@values --> Hash ) multi categorize ( @mapper, *@values --> Hash ) Like C, C transforms a finite list or array of values into a hash representing the categorizations of those values according to a mapper; each hash key represents one possible categorization for one or more of the incoming list values, and the corresponding hash value contains an array of those list values categorized by the mapper into the category of the associated key. Please note that for performance reasons, an implementation is free to C values to the resulting arrays. So you should consider these arrays to be immutable. Unlike C, C always assumes that the return value of the mapper is a list of categories that are appropriate to the current value. Hence, if the mapper returns C<()>, the value is discarded rather than being stored under any key. On the other hand, if the mapper returns a list of categories, the value in question will be pushed into multiple hash locations (while C would merely make a key out of the list returned from the mapper). However, a category may also be a L to indicate a multi-level categorization. In such a case, only the categorization of the lowest level, will actually yield a Hash of Lists. All higher up categorizations, will necessarily always be a Hash of Hashes. Please note that all Lists must have the same number of elements. =item grep multi method grep ( @values: Matcher $test --> Iterable ) multi grep ( Matcher $test, *@values --> Iterable ) C takes a list, array, or sequence of values and returns a lazily evaluated sequence comprised of all of the values from the original list for which the C<$test> smart-matches as true, maintaining their relative order. Here is an example of its use: @friends = @coworkers.grep: { .is_friend }; @friends = grep { .is_friend }, @coworkers; # same This takes the array C<@coworkers>, checks every element to see which ones return true for the C<.is_friend> method, and stores the resulting sequence's values into C<@friends>. Note that, unlike in Perl 5, a comma is required after the C in the multi form. Note that C is an implicit loop, so C and C without an argument will iterate or terminate the C itself, not some loop surrounding the statement containing the C. Use a label if you mean the other thing. =item first multi method first ( @values: Matcher $test ) multi first ( Matcher $test, *@values ) C searches exactly like C but stops testing at the first match and returns just that value. Returns C if no match is found. =item pick multi method pick ( -> Mu ) multi method pick ( @values: Int $num --> Iterable ) multi method pick ( @values: Whatever --> Iterable ) multi pick ( Int $num, *@values --> Iterable ) multi pick ( Whatever, *@values --> Iterable ) C takes a list, array, or sequence of values and returns a sequence of random elements from the list (selected without replacement; see C for dice roll aka replacement semantics). 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(*); A C<.pick> call without arguments returns a single element instead of an iterable container of one element. =item roll multi method roll ( --> Mu ) multi method roll ( @values: Int $num --> Iterable ) multi method roll ( @values: Whatever --> Iterable ) multi roll ( Int $num, *@values --> Iterable ) multi roll ( Whatever, *@values --> Iterable ) C takes a list, array, or sequence of values and returns a random sequence of elements from the list, like rolling N independent dice, where each list element corresponds to one side of your dice. This is also known as "pick with replacement", that is, like pulling one marble out of a bag and putting it back, and doing this N times; see C for the non-replacement semantics. If C<*> is specified as the number, C<*> provides an infinite list of random choices from C<@values>: @byte = (0,1).roll(8); # 8d2 for (1..20).roll(*) -> $die_roll { ... } # 1d20 xx * A C<.roll> call without arguments returns an element of the invocant list instead of a one-element sequence. Note that C is not the same as a 1d6, but always returns C<6> as a degenerate one-sided die. Use C to simulate a six-sided die. =item join multi method join ( @values: Str $separator = '' --> Str ) multi join ( Str $separator = '', *@values --> Str ) 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 multi method map ( @values: Code *&expression --> Iterable ) multi map ( Code $expression, *@values --> Iterable ) C returns a lazily evaluated sequence of values which is comprised of the return value of the expression, evaluated once for every one of the C<@values> that are passed in. The actual return value is a multislice containing one slice per map iteration, unless the expression returns a C, in which case the resulting sequence may not be the same length as the number of values that were passed. Note that C is an implicit loop, so C and C without an argument will iterate or terminate the C itself, not some loop surrounding the statement containing the C. Use a label if you mean the other thing. =item duckmap multi method duckmap ( @values: Code *&expression --> Iterable ) multi duckmap ( Code $expression, *@values --> Iterable ) Like C, C evaluates the expression for each of the values that is passed in. Unlike C, if the evaluation produces an undefined value, a failover looks to see if this element actually contains subelements, and if so, reapplies the duckmap recursively, returning the structured result for that element, so that the structure of the original is (largely) retained in the result. Unlike C, it does not guarantee the same structure, since the mapping expression takes precedence over structure in cases where either would succeed. Because C is defined as a recursive implicit loop, loop controls apply only to the current level of the tree. =item deepmap multi method deepmap ( @values: Code *&expression --> Any ) multi deepmap ( Code $expression, *@values --> Any ) Like C and C, C evaluates the expression for each of the values you give it. Unlike C and C, an element is considered a value only if it does not do the C role. If the element is iterable, the algorithm recurses to produce an identical structure to its input. Elements that are not iterable are considered leaf values and mapped through the supplied expression. Because C is defined as a recursive implicit loop, loop controls apply only to the current level of the tree. =item reduce multi method reduce ( @values: Code *&expression ) multi reduce ( Code $expression ;; *@values ) C takes a sequence of values, accumulates enough values from that sequences to apply C<&expression> to, then feeds that result back into C<&expression> followed by enough additional values taken from subsequent values in the sequence. It repeats this process until no more values are available. The result from the last evaluation of C<&expression> is then returned. If C<&expression> is an operator known to have right associativity, values are pulled in reverse order from the sequence. If an empty sequence is provided and C<&expression> has a known identity value, it is returned. If the identity value is known and the sequence is not empty, but contains one less than enough values, those values are returned (as if C<&expression> had been called with the identity value and those values, but usually without actually evaluating C<&expression>.) If an identity value is not known, and there are not enough values to evaluate C<&expression> once, an empty sequence is usually returned. If a sequence does not produce enough values to perform the last evaluation of C<&expression> the stray values are usually ignored. Note that C is an implicit loop, so C and C without an argument will iterate or terminate the C itself, not some loop surrounding the statement containing the C. Use a label if you mean the other thing. =item reverse multi method reverse ( @values: --> Iterable ) is export multi reverse ( *@values --> Iterable ) Given a sequence of values, C presents a sequence with the same values in the opposite order. If the sequence is not already reified, this usually involves reifying and retaining the values. Note that "reversing" strings is done with C. =item rotate multi method rotate ( @values is copy: Int $n = 1 --> Iterable ) is export Produces a new sequence with the same elements as the input sequence, rotated by the specified amount. See Array::rotate for more info. =item sort multi method sort( @values: *&by --> Iterable ) multi method sort( @values: Ordering @by --> Iterable ) multi method sort( @values: Ordering $by = &infix: --> Iterable ) multi sort( Ordering @by, *@values --> Iterable ) multi sort( Ordering $by, *@values --> Iterable ) 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. 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> (it is an "order preserving" sort.) To sort an array in place use the C<.=sort> mutator form. See L for more details and examples (with C meaning C.) =item unique multi method unique(:@as --> Iterable) multi sub unique(*@values, :&as --> Iterable) Returns a list of unique values from the invocant/argument list, such that only the first occurrence of each duplicated value remains in the result list. C uses C<< &infix:<===> >> semantics to compare whether two objects are the same. The order of the original list is preserved even as duplicates are removed. say .unique # a b c say .unique # a b c (Use C instead if you know the input is sorted such that identical objects are adjacent.) The optional C<:as> parameter allows you to normalize/canonicalize the elements before unique-ing. The values are transformed for the purposes of comparison, but the original values are still emitted in the resulting sequence: say .unique(:as(&lc)) # a B c This makes it possible to effectively compare with other comparison operators, too. For example, if you want to compare with C< infix:<==> > semantics, this might work for you: say +unique 100, 100e0, 200/2, :as(*.Num) # 1 =item squish multi method squish(:&as --> Iterable) multi sub squish(*@values, :@as --> Iterable) Returns a list of values from the invocant/argument list where runs of more than one value are replaced with only the first instance. Like C, C uses C<< &infix:<===> >> semantics to compare whether two objects are the same. Unlike C, this function only removes adjacent duplicates; identical values further apart are still kept. The order of the original list is preserved even as duplicates are removed. say .squish # a b c say .squish # a b c b a The optional C< :as > parameter, just like with C< unique >, allows values to be temporarily transformed before comparison. =item min multi method min( @values: *&by --> Any ) multi method min( @values: Ordering @by --> Any ) multi method min( @values: Ordering $by = &infix: --> Any ) multi min( *@values, Ordering :@by --> Any ) multi min( *@values, Ordering :$by --> Any ) 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. 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 multi method max( @values: *&by --> Any ) multi method max( @values: Ordering @by --> Any ) multi method max( @values: Ordering $by = &infix: --> Any ) multi max(*@values, Ordering :@by, --> Any ) multi max(*@values, Ordering :$by, --> Any ) 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. 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 multi method minmax( @values: *&by --> Any ) multi method minmax( @values: Ordering @by --> Any ) multi method minmax( @values: Ordering $by = &infix: --> Any ) multi minmax( *@values, Ordering :@by --> Any ) multi minmax( *@values, Ordering :$by --> Any ) 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. 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 multi method any( @values: --> Junction ) multi any( *@values --> Junction ) 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 multi method all( @values: --> Junction ) multi all( *@values --> Junction ) 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 multi method one( @values: --> Junction ) multi one( *@values --> Junction ) 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 multi method none( @values: --> Junction ) multi none( *@values --> Junction ) 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 = * ) multi method comb ( Str $matcher, Int $limit = * ) Treats a sequence values as a string (by simply Cing them together), and calls C<.comb> on that string with the same parameters. See C. =item combinations multi method combinations ( Int $of ) multi method combinations ( Range $of = 0 .. * ) multi combinations ( $n, $k ) Returns all combinations of the list taken N at a time (specified by the C<$of> parameter). If the range option is taken, then the range is iterated, and for each integer N in the range, appends all combinations taken N at a time to the resulting list. If the max of the range is greater than the size of the list, iteration stops at the size of the list. Hence, if the default of C<0..*> is taken, the first return value will be an empty array, and the final return value will be an array containing every value in the list. The return value is a sequence or container of (presumably immutable) values. (Note: When used on actual sets and other iterable structures, specialized versions of this method are allowed to bypass turning it into a list first. Also, the return values are allowed to be specialized to any non-flattening container, so that subsets of sets can actually be a set of sets. If the ordering of the input doesn't matter, neither does the ordering of the subsets.) Note that, without an argument, the first returned combination will always be the empty list, and the last combination will always be the entire list. It is erroneous to ask for the combinations of any infinite list. The compiler is allowed to complain if it notices, however. The functional form assumes it is working on a list of integers C<^$n> taken C<$k> at a time. =item permutations multi method permutations ( ) multi permutations ( $n ) Similar to C, but returns permutations instead. (Types such as C are converted to a list of individual values before permuting them.) The functional form assumes it is working on a list of integers C<^$n>. =item rotor multi method rotor ( *@cycle, :$partial ) Takes multiple cyclical slices of a sequence as specified by C<@cycle>, which you can think of as a rotory cutter that punches out multiple slices depending on the arrangement of the blades (or teeth, if you prefer a gear analogy). Since it's cyclical, you may apply a rotor to an infinite list lazily. Each specifier in the cycle specifies how many elements to take (the "slice") and, optionally, how many to omit (the "gap"). The cycle repeats if C<@cycle> runs out before the sequence does. The rotor stops if the sequence runs out first, that is, if there are insufficient values remaining to create the entire next slice (ignoring any associated gap). If :partial is specified, the final partial slice is returned at the end, if it is not empty. Here we slice the alphabet into alternating slices of size 2 and 3: my @list = 'a'...'z'; @list.rotor(2,3) # ab, cde, fg, hij...uv, wxy @list.rotor(2,3, :partial) # ab, cde, fg, hij...uv, wxy, z It is allowed to specify an infinite cycle, in which case it will never repeat, at least not internally. The supplied list may of course repeat itself instead. Hence these two calls produce the same result: @list.rotor(2,3) @list.rotor((2,3) xx *) Each slice specifier may be either an integer or a pair. If it is a pair, the key is taken as the number of elements to take in the slice, and the value is taken as the size of the gap. If the specifier is an integer, it is taken as the size of the slice, and the gap is taken as 0. In other words, these are equivalent: @list.rotor(3) @list.rotor(3 => 0) A non-zero gap or overlap may be specified only via the pair form: @list.rotor(2 => 1) # take two, skip one @list.rotor(2 => -1) # take two, back up one =item pairup multi method pairup ( ) Turns a sequence of mixed keys, values, and pairs into a sequence of pairs in the same way that a hash composer does, only without creating the hash. While there is more to process, the next value is examined. If it is a Pair, it is passed through unchanged. Otherwise a second value is also taken from the list and those two values together are turned into a pair. It is an X::Pairup::OddNumber error if there is no next value. (It is not an error if the second value happens be a pair; if so, it merely becomes the value paired with the key of the first value.) Obviously you cannot create pairs where the keys are Pairs using this function. Use a map or some such for that. =item invert multi method invert ( --> Iterable ) is export { self.map: -> $p { $.value »=>» $.key } } Produces a backmapping of values to keys, expanding list values into multiple pairs. (The C<< »=>» >> expands the value if it is a list.) The invocant must be a list containing only Pairs, and throws an error if anything that is not a Pair is passed. To invert key/value lists, use C<.pairup> first: @kv.pairup.invert Likewise if you wish to invert the implicit indices of an array or list, you must call C<.pairs> first: .pairs.invert # ('a' => 0, 'b' => 1, 'c' => 2) (You may call C<.invert> directly on a hash, because a hash naturally listifies to a list of pairs.) =back =head2 Array All these methods are defined in the C role/class. role Array does List {...} =over =item new multi method new(*@args --> Array ) Constructs a new C containing the arguments passed to C. =item shape method shape (@array: --> List ) is export Returns the declared shape of the array, as described in S09. =item end method end (@array: --> Any ) 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. So that the degenerate case of an empty range works correctly, C<-1> is returned if the array is empty. (If you actually try to index with C<-1>, you'll get a failure.) =item elems method elems (@array: --> Int ) is export Returns the length of the array counted in elements. =item delete (DEPRECATED) The "delete" method is considered to be a deprecated internal method: the normal way to mark an element as deleted, is to apply the C<:delete> adverb to a subscripting operation. =item :delete This adverb may be applied to any subscripting operation. The operation returns the elements normally, but reads them out destructively. =item exists (DEPRECATED) The "exists" method is considered to be a deprecated internal method: 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 multi method pop ( @array: --> Scalar ) is export Remove the last element of C<@array> and return it. If C<@array> is empty returns a failure. =item push multi method push ( @array: *@values --> Array ) is export Adds all the values to the end of C<@array> eagerly. Returns the modified array. =item plan multi method plan ( @array: *@list --> Array ) 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 multi method rotate ( @array is copy: Int $n = 1, Int *@n --> Array ) 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 rotation 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 multi method shift ( @array: --> Scalar ) is export Remove the first element from C<@array> and return it. If C<@array> is empty returns a failure. =item splice multi method splice( @array is rw: $offset = 0, $size = Inf, *@values --> Any ) 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. A WhateverCode whose argument is the number of elements in the C<@array> may also be used. C<$size> is the number of elements to remove from C<@array>. A WhateverCode similar to C<$offset> may be used instead (note that this specifies a position, not an actual number of elements to remove). 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 sequence starting at C<1>. 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. C<$offset> and C<$size> will be treated as C. The function fails if either parameter is negative, or undefined. Either of C<$offset> or C<$size> may be specified relative to the length of the array using a WhateverCode whose argument will be the number of elements in the array. While it is illegal for the offset to be larger than the size of the array, it is allowed for the final position to be off the end of the array; in this case the entire rest of the array is spliced, whatever is available. =item unshift multi method unshift ( @array: *@values --> Array ) 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 antipairs =item enums =item values multi method keys ( @array: ) is export multi method kv ( @array: ) is export multi method pairs ( @array: ) is export multi method antipairs ( @array: ) is export multi method enums ( @array: ) is export multi method values ( @array: ) is export Iterates the elements of C<@array>, in order. 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 class. class Hash is EnumMap {...} =over 4 =item delete (DEPRECATED) The "delete" method is considered to be a deprecated internal method: the normal way to remove a key from a hash, is to apply the C<:delete> adverb to a subscripting operation. =item :delete This adverb may be applied to any subscripting operation. The operation returns the elements normally, but reads them out destructively. =item exists (DEPRECATED) The "exists" method is considered to be a deprecated internal method: 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 keys =item kv =item pairs =item antipairs =item enums =item values multi method keys ( %hash: ) is export multi method kv ( %hash: ) is export multi method pairs ( %hash: ) is export multi method antipairs ( %hash: ) is export multi method enums ( %hash: ) is export multi method values ( %hash: ) 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. 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 no longer supported. Use the C<.buckets> property instead. =item any multi method any( %hash: --> Junction ) 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 multi method all( %hash: --> Junction ) 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 multi method one( %hash: --> Junction ) 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 multi method none( %hash: --> Junction ) is export Returns a junction which will only match against another value if none of the keys in the hash matches. =item antipairs multi method antipairs ( %hash: --> List ) is export { %hash.map: { .value => .key } } Produces a simple backmapping of values to keys, like C<.pairs> but with each returned pair returned as an antipair, that is, a pair with key and value exchanged. Unlike the C method, there is no attempt to expand list values into multiple pairs. =item invert multi method invert ( %hash: --> List ) is export { %hash.map: { .value »=>» .key } } Produces a backmapping of values to keys, but unlike C<.antipairs>, expands list values into multiple pairs. (The C<< »=>» >> expands C<.value> if it is a list.) This function is essentially a shortcut for C<.pairs.invert>, but bypasses the creation of pairs only to invert them. =item push multi method push ( %hash: *@values --> Hash ) 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 inverting a hash twice produces a hash equivalent to the original hash. =back =head1 Classes and Roles This documents Buf, List, Range, Set, Bag, Junction, Array, Hash, MixHash, SetHash, BagHash, Pair, and PairMap. =head2 Range class Range does Positional does Iterable { method min() {...} method max() {...} method bounds() returns List {...} method excludes-min {...} method excludes-max {...} method sample {...} } =head3 Methods =over =item sample multi method sample ( $range: Int $num = 1 --> List ) multi method sample ( $range: Whatever --> List ) Returns a lazy list of C values, taken as linearly distributed samples from the real interval specified by the invocant. The argument, if any, indicates how many samples to return. Hence, C<(^1).sample> is equivalent to C, and C<(^10).sample(*)> is equivalent to C. Ranges with exclusions other than C<..^> may be less efficient by virtue of having to generate from a larger interval, throwing out values that are outside the specified interval. =back =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 method decode($encoding = $?ENC, $nf = $?NF --> Str ) 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. =item subbuf method subbuf($from, $elems?) returns Buf:D Returns a part of the original buffer, starting from index C<$from> and taking C<$elems> elements (or to the end of the buffer, if not provided). The method fails with C if either C<$from> or C<$elems> are negative. The method also fails if C<$from> is larger than the amount of elements in the buffer. C<$from> may be specified relative to the end of the string using a WhateverCode: Buf.new(0x00, 0xFF).subbuf(*-1, 1) =item subbuf-rw method subbuf-rw( $from; $elems?) is rw A version of C<.subbuf> that returns a writable reference to a part of a buffer: $b.subbuf-rw($from,$to) = Buf.new(0x00, 0x77); =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 antipair multi method antipair ( $pair: --> Pair ) is export { $pair.value => $pair.key } Returns new pair with key and value swapped. Note singular spelling, since this operates only on one pair. =item invert multi method invert ( $pair: --> List ) is export { $pair.value »=>» $pair.key } Note that this is not a simple exchange, but splits pairs with C values into multiple pairs in support of database inversion operations (when used along with C). Equivalent to C if no values are C. =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 or objects. (Sets are notionally "object hashes", that is, hashes that allow more than just strings as keys; as such, they are subject to C<===> equality rather than C equality.) A C responds to hash operators as if it were a C. that is, when used as a hash, a set always treats the set's elements as the keys of the hash, returning C for existing set elements, and C for any key not found in the set. See C for a container that can represent different sets as keys are added or deleted. Regardless of their behavior as hashes, set (and bag) types do not flatten in list context; in the absence of explicit interpolation instructions (such as use of the C<@> sigil or C<.keys> method) they are returned as items in list context. On the other end, the constructors for set and bag types do not automatically interpolate the contents of sets or bags (or any other other item type). They simply take the list of objects slurped in and turn them into a set. Together these rules allow us to constructs sets and bags containing sets and bags as elements. Use the C composer to construct a set of the elements of the list. The empty set may be indicated with either C or C<∅> (U+2205 EMPTY SET). The C composer will very literally make a set of whatever you pass it; in particular, it will make a set of Pairs if you try to pass it a list of Pairs (recall that a hash returns a list of Pairs in list context). To create a set from the keys of a list of Pairs, use a C coercion rather than a constructor. Or to create a set from a hash, use the C<.keys> or C<:k> to extract only the keys. =over =item pick multi method pick ( $set: Int $num = 1 --> Any ) multi method pick ( $set: Whatever --> Any ) Works like an ordinary list C. =item roll multi method roll ( $set: Int $num = 1 --> Any ) multi method roll ( $set: Whatever --> Any ) Works like an ordinary list C. =item combinations multi method combinations ( Int $of ) multi method combinations ( Range $of = 0 .. * ) Works as if the set were turned into a list of elements and then the combinations were turned back into a list of sets, ordered by increasing size. You may, of course, turn that list back into a set of sets. Note that, without an argument, this method basically calculates the powerset. =back =head2 SetHash A mutable Set container, represented as C. =head2 Bag class Bag does Associative {...} A collection of values or objects that work just like sets, except that they need not be unique. The count of each value or object is represented by an associative mapping from each key value/object to its replication number. The C<.total> method returns the sum of all replication values. The C<.minpairs> and C<.maxpairs> methods return the pairs with the minimum and maximum replication number. Sets and bags do not flatten into list context, nor do the constructors interpolate items passed to them, even if they look like sets or bags. (To create a bag from a list of Pairs or a hash, use a C coercion rather than a constructor.) =over =item pick multi method pick ( $bag: Int $num = 1 --> Any ) multi method pick ( $bag: Whatever --> Any ) multi method pickpairs ( $bag: Int $num = 1 --> Pairs ) multi method pickpairs ( $bag: Whatever --> Pairs ) 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 underlying metaphor for picking is that you're pulling colored marbles out a bag. (For "picking with replacement" see C instead.) 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>/C<.pickpairs> invocation maintains its own private state and has no effect on subsequent C<.pick>/C<.pickpairs> invocations. The C<.pickpairs> version returns the grabbed values as a list of C objects, whose keys are the keys and whose values are the replication values. =item roll multi method roll ( $bag: Int $num = 1 --> Any ) multi method roll ( $bag: Whatever --> Any ) 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 C used. The underlying metaphor for rolling is that you're throwing C<$num> 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 C<$num> 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 number of sides with the same color. (For "picking without replacement" see C instead.) Rolling requires no temporary state. =item kxxv method kxxv (-->List) Returns a list of the keys of the bag, with each key multiplied by its replication factor (hence the name: .k xx .v). =back =head2 BagHash A mutable C container, represented as C. =head2 QuantHash role QuantHash[::T, $default = Any] does Mixy does Associative {...} A C represents a mutable set of objects, represented as the keys of a C. When asked to behave as a list it ignores its C<.values> and returns only C<.keys> (possibly replicated by weight in the case of bag types). C and C are derived from this type, but constrain their hash values to be C and C, respectively. A C automatically deletes any key whose corresponding value goes to the default value for the hash. For any C, the C<.total> 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 standard 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, automatically deleting any entry if its value goes to that (false) default value. =over =item grab multi method grab ( $bag: Int $num = 1 --> Any ) multi method grab ( $bag: Whatever --> Any ) multi method grabpairs ( $bag: Int $num = 1 --> Any ) multi method grabpairs ( $bag: Whatever --> Any ) Like C, a C returns a random selection of elements, weighted by the values corresponding to each key. Unlike C, it works only on mutable structures. Use of C on an immutable structure results in an exception (much like C would). 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.) Grabbing decrements the grabbed key's replication value by one (deleting the key when it goes to 0). By definition, C<.total> 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 MixHash 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: --> List) 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 AUTHORS Rod Adams Larry Wall Aaron Sherman Mark Stosberg Carl Mäsak Moritz Lenz Tim Nelson =for vim:set expandtab sw=4: