=head1 NAME

Perl6::Overview::Data - Data Types

=head1 DESCRIPTION

=head2 Scalar (C<$>)

    list $foo        # $foo
        +$foo        # $foo as Num
        ~$foo        # $foo as Str
        ?$foo        # $foo as Bool
        "$foo"       # $foo as Str
    item $foo        # $foo

=head3 Scalar -> Str

    .chomp    # Returns chomped string with a .newline property giving the
                newline removed
    .chop
    .ord
    .lc
    .lcfirst
    .uc
    .ucfirst
    .chars    # Length in characters
    .graphs   # Length in graphemes
    .codes    # Length in codepoints
    .bytes    # Length in bytes
    .tr
    .reverse
    .split(/sep/)
    .hex
    .oct
    .index
    .rindex
    .substr
    .trans
    .capitalize

=head3 Scalar -> Num

    .abs
    .cos
    .exp
    .int
    .log
    .rand
    .sin
    .sqrt
    .chr
    .floor
    .ceil
    
=head2 Array (C<@>)
    
    list @foo        # List of elements
        +@foo        # @foo.elems
        ~@foo        # join ' ', @foo
        ?@foo        # ? @foo.elems
        "@foo[]"     # join ' ', @foo
         @foo[i]     # subscript
         @foo[i, i]  # slice
         @foo[i; i]  # multi-dimensional access
    item @foo        # \@foo

=head3 Methods

    .elems          # Number of elements
    .join($sep)
    .map:{ ... }
    .grep:{ ... }
    .pop
    .push($elem)
    .shift
    .unshift($elem)
    .reverse
    .sort( { cond }, { cond }, ... )
    .kv            # return index,value pairs
    .pairs         # return Pair objects instead
    .uniq
    
=head3 Shapes

    XXX - someone summarize shapes and multi-dimension syntax

=head3 Constructors

    ARRAY = LIST
    [ LIST ]       # Array object

=head3 Lists vs. Arrays

    (42)       # this is neither a list nor an array,
                # but a scalar (the Num 42)
    (42,)      # this is a one-element list
    list 42    # this is a one-element list
    (42,23)    # this is a two-element list

    []         # this is a zero-element array
    [42]       # this is a one-element array
    [42,]      # this is a one-element array
    [42,23]    # this is a two-element array

List construction (via the comma operator, &infix:<,>), does not create
containers, meaning that the elements are aliases:

    ($foo,$bar)[0] =:= $foo;  # true
    ($foo,$bar)[0]   = $baz;  # $foo changed to $baz

This also means that

    (42,23)[0] = 17;  # is a fatal error ("can't modify constant")
    # Similarly, you can't shift(), pop(), unshift() etc. arrays created by
    # the comma operator:
    shift (42,23);    # dies

By contrast, Array construction by the [] operator, &circumfix:<[ ]>,
does create new containers:

    [$foo,$bar][0] =:= $foo;  # false
    [$foo,$bar][0]   = $baz;  # $foo not changed

    shift [42,23];            # lives (but the Array is discarded after
                                # the operation)

    my @array = (42,23);
    shift @array;             # works too, as assignment to an array
                                # implicitly creates new containers.

(While in Perl 5 the distinction between lists and arrays was often
implicit, this distinction is made explicit Perl 6. Amongst other
reasons, this is because Array objects in scalar context is just itself,
it's no longer the parentheses which create list context, but a slurpy
array in some signature. In Perl 6, the comma operator creates lists,
parens are only for grouping:

    # Perl 5
    sub foo { (1,2,3) }
    my $scalar = foo();  # 3
    my @array  = foo();  # (1,2,3)

    # Perl 6
    sub foo { (1,2,3) }
    my $scalar = foo();  # [1,2,3]
    my @array  = foo();  # (1,2,3)

Also note that list context, i.e. the context supplied by a slurpy array in
a signature, automatically flattens arrays and hashes (but not scalars
containing array or hash objects):

    sub this_provides_list_context (*@things) { @things[0] }
    my @foo = <a b c>;
    my @bar = <d e f>;
    say this_provides_list_context(@foo, @bar);
    # "a", not the stringification of @foo (which would be "a b c").

The list constructing comma operator supplies this list context:

    sub *infix:<,> (*@things) {...}

This also explains why (@foo, @bar) does not create an array containing two
elements, but a List containing C<@foo + @bar> items. (Like
C<@foo.concat(@bar)> in other languages.))

=head2 Hash (C<%>)

    list %foo        # List of pairs
        +%foo        # +%foo.keys
        ~%foo        # ???
        ?%foo        # ? %foo.keys
        "%foo{}"     # ???
         %foo{k}     # subscript
         %foo{k, k}  # slice
         %foo<>      # %foo{<>}
         %foo<<>>    # %foo{<<>>}
         %foo{k; k}  # multi-dimensional access
    item %foo        # \%foo

=head3 Methods

    .delete($key)
    .exists($key)
    .keys
    .values
    .kv                # List of key, value, key, value, ...
    .pairs             # List of Pair having the same

    Shapes: 

    XXX - help me

    Constructors:

    HASH = LIST
    { PAIR, PAIR, ... }   # anonymous object
    hash( LIST )

=head2 Pair

    list $foo        # $foo   # object, so doesn't flatten to $k, $v
        +$foo        # ???
        ~$foo        # ???
        ?$foo        # ???
        "$foo"       # ???
    item $foo        # $foo

=head3 Methods

    .kv      # $key, $value
    .key
    .value

=head3 Constructors (all anonymous)

    :key            # key => 1
    :key{'value'}   # key => 'value'
    \__ thus: :key<>, :key<<>>
    key => 'value'  # key => 'value' (LHS auto-quoted)

=head2 Things with blocks

    Named               Anonymous             See also
    class   Foo { }     class   { }           oo
    role    Foo { }     role    { }           oo
    sub     foo { }     sub     { }, or { }   sub
    method  foo { }     method  { }           oo, sub
    macro   foo { }                           sub
    rule    foo { }     rule    { }           rules
    grammar Foo { }     grammar { }           rules
    package Foo { }     package { }           mod
    module  Foo { }     module  { }           mod

=head2 Variable names, containers, values, etc.

A variable name is '$foo', '@foo', '%foo', etc.

In the symbol table/the lexical pad, links from variable names to
their containers are stored.

A variable with ... sigil always points to a ... container:
    $  -->  Scalar
    @  -->  Array
    %  -->  Hash
    &  -->  Scalar
    ^  -->  Scalar

A scalar container holds a single cell. This cell can either be constant or
modifiable. Binding replaces the cell.
    $a := $b;  # $a's cell slot points to $b's cell.
    $b := $c;  # $b's cell slot points to $c's cell.
                # $a's cell slot still points to what used to be $b's cell.

Array and hash containers hold many cells. Again, binding replaces a cell.
    @array[$idx] := $b;  # @array's cell slot number $idx points to $b's
                        # cell.
    $b := $c;            # $b's cell slot points to $c's sell.
                        # @array's cell slot number $idx still points to
                        # what used to be $b's cell.

Cells hold the actual values, for example the Num 3 or the Str "Pugs".

To summarize:
    '$foo' entry in the lexical pad points to...
    the container of '$foo'. The container holds...
    a cell, which in turn holds...
    $foo's value.

Examples:

    $foo = 42;
    # '$foo' --> $foo's container --> cell 123 --> Num 42

    $bar = \$foo;
    # '$bar' --> $bar's container --> cell 456 --> Ref -->
            --> $foo's container --> cell 123 --> Num 42

    $grtz = 23;
    @array = ($foo, $grtz)
    # '@array' --> @array's container -->
    #          --> [
    #                 0 --> cell 111 --> Num 42,
    #                 1 --> cell 222 --> Num 23,
    #              ]
    # (Changing $foo or $grtz does not have an effect on @array yet.)

    @array[0] := $foo;
    # '@array' --> @array's container -->
    #          --> [
    #                 0 --> cell 123 --> Num 42,
    #                 1 --> cell 222 --> Num 23,
    #              ]
    # (Changing $grtz still does not have an effect on @array. Changing $foo
    # (by assignment) does have an effect on @array. Re-binding $foo to some
    # other variable causes further assignments to $foo to have no effect on
    # @array again.)

C<=:=> tests whether the cell slots of two containers $a and $b point to the
same cell.

    $a = 42;
    # '$a' --> $a's container --> cell 42 --> Num 42

    $b = 42;
    # '$b' --> $b's container --> cell 23 --> Num 42
    $a =:= $b;  # false, of course

    $b := $a;
    # '$b' --> $b's container --> cell 42 --> Num 42

C<===> tests whether the eternal values of two immutable cells are
identical; for two mutable cells, it evaluates the same way as C<=:=>.

    42 === 42;  # true

    my $a = 42;
    my $b = 42;
    $a =:= $b;  # false, of course
    $a === $b;  # true

    (1,2) === (1,2); # true
    [1,2] === [1,2]; # false

C<eqv> tests whether current snapshots of the values of two mutable cells
are identical; for two immutable cells, it evaluates the same way as
C<===>.

    [1,2] eqv [1,2];  # true

    my $a = [1,2];
    my $b = [1,2];
    $a === $b;  # false, of course
    $a eqv $b;  # true

Method calls on arrays and hashes go to the container, whereas method
calls on scalars go to the cell.  

    $dog.bark();   # method call dispatched to $dog's value, i.e. a Dog object.
    @array.elems;  # method call dispatched to @array's container, an Array object

Using the .VAR postfix macro, you can force a method call to a scalar to
go to its container.  An example of a method on a scalar is .exists,
which tests whether the container's cell slot is nonempty:

    sub foo ($a?) { $a.VAR.exists }
    foo();    # false
    foo(42);  # true

.exists on array and hash containers test whether an element of a given
index/name exists:

    my @array = (1,2,3);
    @array.exists(1);   # true (@array[1] is 2)
    @array.exists(3);   # false

    my %hash = (a => 1, b => 2);
    %hash.exists("a");  # true (%hash<a> is 1)
    %hash.exists("c");  # false)

(Reading t/operators/binding/*, t/operators/identity.t, and
t/operators/value_equivalence.t is strongly recommended.)
