
=encoding utf8

=head1 TITLE

DRAFT: Synopsis 32: Setting Library - Containers.pod

=head1 AUTHORS

    Rod Adams <rod@rodadams.net>
    Larry Wall <larry@wall.org>
    Aaron Sherman <ajs@ajs.com>
    Mark Stosberg <mark@summersault.com>
    Carl Mäsak <cmasak@gmail.com>
    Moritz Lenz <moritz@faui2k3.org>
    Tim Nelson <wayland@wayland.id.au>

=head1 VERSION

    Created: 19 Feb 2009 extracted from S29-functions.pod

    Last Modified: 12 May 2009
    Version: 8

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<Positional> role implies the ability to support C<< postcircumfix:<[ ]> >>.

=head2 Associative

    role Associative {...}

The C<Associative> role implies the ability to support C<< postcircumfix:<{ }> >>.

=head2 Container

    role Container {...}

=over

=item cat

 our Cat multi cat( *@@list )

C<cat> reads arrays serially rather than in parallel as C<zip> 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<Cat> in item context emulates the C<Str> interface lazily.

=item roundrobin

 our List multi roundrobin( *@@list )

C<roundrobin> is very similar to C<zip>.  The difference is that
C<roundrobin> 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 List of Capture multi zip ( *@@list )
 our List of Capture multi infix:<Z> ( *@@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<zip> 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<eager>
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<Z> is an infix equivalent for zip:

 for @a Z @b Z @c -> $a, $b, $c {...}

In C<@@> context a List of Array is returned instead of flat list.

=back

=head2 List

The following are defined in the C<List> role/class:

    role List does Container does Positional {...}

=over

=item cat

 our Cat multi cat ( @values )

Returns a C<Cat> object, a concatenated version of the list that does the C<Str>
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<join('')>, except that C<join> is always eager.  However, a C<Cat>
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<cat> of a C<cat> is also lazy, and in fact, you just
get a flat cat because C<cat> in a list context is a no-op.  The C<Cat>
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<Cat> 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<classify> 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<red>.map:{.owner});

=item grep

 our List multi method grep ( @values: Matcher $test )
 our List multi grep ( Matcher $test, *@values )

C<grep> 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<Matcher>
in the multi form.

=item first

 our Item multi method first ( @values: Matcher $test )
 our Item multi first ( Matcher $test, *@values )

C<first> works exactly like C<grep> but returns only the first matching value.

=item pick

 our multi method pick ( @values: Int $num = 1, Bool :$repl )
 our multi method pick ( @values: Whatever, Bool :$repl )
 our multi pick ( Int $num, Bool :$repl, *@values )
 our multi pick ( Whatever, Bool :$repl, *@values )

C<pick> takes a list or array of values and returns a random
selection of elements from the list (without replacement unless
C<:repl> 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, :repl);
    for (1..20).pick(*, :repl) -> $die_roll { ... }

Due to the normal semantics of returning a C<Capture>, 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<join> returns a single string comprised of all of the elements
of C<@values>, separated by C<$separator>.

Given an empty list, C<join> returns the empty string.

The separator defaults to the null string.  To join with space,
just coerce to C<Str>.

=item map

 our List of Capture multi method map ( @values: Code *&expression )
 our List of Capture multi map ( Code $expression, *@values )

C<map> 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<flip>.

=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:<cmp> )

 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:<cmp> >> (Schwartzian Transform).

C<Ordering> is as described in L<"Type Declarations">.  Any
C<Ordering> may receive either or both of the mixins C<descending>
and C<canon(Code $how)> to reverse the order of sort, or
to adjust the case, sign, or other order sensitivity of C<cmp>.
(Mixins are applied to values using C<but>.)  If a C<Signature>
is used as an C<Ordering> then sort-specific traits such as C<is
canon($how)> 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<http://www.nntp.perl.org/group/perl.perl6.language/16578>
for more details and examples (with C<is insensitive> meaning
C<is canonicalized(&lc)>.)

=item min

 our multi method min( @values: *&by )
 our multi method min( @values: Ordering @by )
 our multi method min( @values: Ordering $by = &infix:<cmp> )

 our multi min( Ordering @by,  *@values )
 our multi min( Ordering $by,  *@values )

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<Ordering> is as described in L<"Type Declarations">.  Any
C<Ordering> may receive the mixin C<canonicalized(Code $how)> to
adjust the case, sign, or other order sensitivity of C<cmp>.
(Mixins are applied to values using C<but>.)  If a C<Signature>
is used as an C<Ordering> then sort-specific traits such as C<is
canonicalized($how)> are allowed on the positional elements.

For a C<min> 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:<cmp> )

 our multi max( Ordering @by,  *@values )
 our multi max( Ordering $by,  *@values )

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<Ordering> is as described in L<"Type Declarations">.  Any
C<Ordering> may receive the mixin C<canonicalized(Code $how)> to
adjust the case, sign, or other order sensitivity of C<cmp>.
(Mixins are applied to values using C<but>.)  If a C<Signature>
is used as an C<Ordering> then sort-specific traits such as C<is
canonicalized($how)> are allowed on the positional elements.

For a C<max> function that does not require an ordering, see the
C<[max]> 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 C<join>ing them together), and calls
C<.comb> on that string with the same parameters. See C<Str::comb>.

=back

=head2 Array

All these methods are defined in the C<Array> role/class.

    role Array does List {...}

=over

=item shape

 our Capture 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.  (Sparse array
types should return the actual number of elements, not the distance
between the maximum and minimum 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<is shape()> 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<Capture> of C<Bool> 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.

=item push

 our Array multi method push ( @array: *@values ) is export

Add to the end of C<@array>, all of the subsequent arguments and
returns the modified array.

=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.

=item splice

 our multi method splice( @array is rw: Int $offset = 0, Int $size?, *@values ) is export

C<splice> 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<splice>.

If C<@array> is multidimensional, C<splice> operates only on the first
dimension, and works with Array References.

C<splice> returns a C<Capture> of the deleted elements, which behaves as
expected in either list or scalar context.


=item unshift

 our Array multi method unshift ( @array: *@values ) is export

C<unshift> 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 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<grep>.)

What is returned at each element of the iteration varies with function.
C<values> returns the value of the associated element; C<kv> returns
a 2 element list in (index, value) order, C<pairs> a C<Pair(index, value)>.

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<kv @array> returns the same as C<zip(^@array; @array)>

=back

=head2 Hash

The following are defined in the C<Hash> 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<Capture> of C<Bool> 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 values ( %hash: Matcher $keytest? ) is export

Iterates the elements of C<%hash> in no apparent order, but the order
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<keys> only returns the key; C<values> the value; C<kv> returns both as
a 2 element list in (key, value) order, C<pairs> a C<Pair(key, value)>.

Note that C<kv %hash> returns the same as C<zip(keys %hash; values %hash)>

The lvalue form of C<keys> 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<Positional>.]

=item push

 our Int multi method push ( @hash: *@values ) is export

Like hash assignment insofar as it accepts either C<Pair> objects or
alternating keys and values; however, unlike assignment, when
a duplicate key is detected, coerces the colliding entry's value to an
array and pushes the Pair'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

This documents Buf, List, Seq, Range, Set, Bag, Junction, Array, Hash, KeyHash, KeySet,
KeyBag, Pair, and Mapping.

=head2 Seq

    class Seq does Positional {...}

=head2 Range

    class Range does Positional {
        method from() {...}
        method to() {...}
        method min() {...}
        method max() {...}
        method List minmax() {...}
    }

=head2 Buf

    class Buf does Positional {...}

A mutable container for an array of integer values in contiguous
memory. The default constructor takes a slurpy array parameter of
integers, the largest of which determines the actual type. So

    Buf.new(:16<c3>, :16<B6>) # or
    Buf.new(195, 182)         # which is exactly the same

returns a C<buf8> containing two C<uint8> items, while

    Buf.new(256)

returns a C<buf16> which consists of a single C<uint16>.

To explicit request a C<Buf> 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<utf8> (which only allows valid
UTF-8 byte sequences) exist and provide similar constructors. See
L<S02/Built-In Data Types>.

=head3 Methods

=item decode

    our Str method decode($encoding = $?ENC, $nf = $?NF)

Decode the C<Buf> into a C<Str>. For subtypes that know their encoding (like
C<utf8>, C<utf16>) the C<$encoding> parameter defaults to their intrisic
encoding instead.

=head3 C<Buf> Operators

Two C<Buf> objects of the same bit size can be compared with the same
operators as strings (in particular C<eq>, C<lt>, C<le>, C<gt>, C<ge>,
C<ne> and C<leg>), but actually compares the stored integers, not
characters. Concatenating two compatible C<Buf>s produces an object of the
most specific type possible, for example C<buf8.new() ~ utf8.new()> results in
a C<buf8> object.

Comparing or concatenating two C<Buf> objects of different bit sizes,
or a C<Buf> that doesn't know its encoding with a C<Str> throws an exception.

Likewising coercing an encoding-unaware C<Buf> to C<Str> dies.

[Conjecture: The behaviour of encoding-aware C<Buf> objects on string
operators is intentially not defined yet, because I have no idea what
implications on speed and usage they might have --moritz].

=head2 Pair

    class Pair does Associative {...}

The value of a pair is mutable; the key is not.

=item invert

    our List multi method invert ( $pair: ) is export {
     $pair.value X=> $pair.key
    }

=head2 Mapping

    class Mapping does Associative {...}

An immutable hash value, essentially.  The keys may
not contain duplicates, while the values may.

=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<True> for set elements.
See C<KeySet> for a container that can represent different sets
as keys are added or deleted.

=over

=item pick

 our multi method pick ( $set: Int $num = 1, Bool :$repl )
 our multi method pick ( $set: Whatever, Bool :$repl )

Like an ordinary list pick, 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<KeySet> is the
mutable form of C<Set>.  A C<Set> responds to hash operators as
if it were a C<Hash of True>.

=back

=head2 KeySet

A mutable Set container, represented as C<KeyHash of True>.

=head2 Bag

    class Bag does Associative {...}

=over

=item pick

 our multi method pick ( $bag: Int $num = 1, Bool :$repl )
 our multi method pick ( $bag: Whatever, Bool :$repl )

Like an ordinary list pick, 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<KeyBag> is the
mutable form of C<Bag>.  A C<Bag> responds to hash operators as
if it were a C<Hash of UInt>.

=back

=head2 KeyBag

A mutable C<Bag> container, represented as C<KeyHash of UInt>.

=head2 KeyHash

    class KeyHash does Associative {...}

A KeyHash represents a mutable set of values, represented as the keys
of a C<Hash>.  When asked to behave as a list it ignores its values
and returns only C<.keys>.  C<KeySet> and C<KeyBag> are derived from
this type, but constrain their values to be C<Bool> and C<UInt>,
respectively.  A C<KeyHash> automatically deletes any key whose
value goes false.

=head2 KeyWeight

A C<KeyHash of Num>; like a C<KeyBag> but may have non-integral
weights for use in weighted picking.

=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<Set()>.  Note, however, that the set of eigenstates
for a C<none> junction defines the values that are *not* there,
so the resulting C<Set> will be the I<complement> to the universe of
values recognized by the junction!  Also note that C<any> and C<all>
junctions represent I<sets> of sets of items, not sets of items.
Since set items are by definition unique, only the C<one> 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.
