
=encoding utf8

=head1 TITLE

Synopsis 8: Capture and Parcel

=head1 AUTHORS

    Daniel Ruoso <daniel@ruoso.com>

=head1 VERSION

    Created: 20 Sep 2009

    Last Modified: 23 Jan 2010
    Version: 2

=head1 Introduction

Unlike most programming languages, the data structure that is used to
send the parameters into a routine invocation (be it a method or a
sub) is exposed to the language as a built-in type like any
other. This represents a very important aspect of the Perl 6 runtime
requirements.

Additionally to the fact that this data structure is visible in the
language type system, it is not assumed that the capture is a native
type, which means that the internal representation of the data is
subject to change. The only thing the runtime can assume is the API
described here.

Of course the runtime can cheat whenever it knows the capture is
implemented by its own internal data structure for optimization
purposes, but it should allow the use of foreign types when invoking a
routine, as long as the object says true to C<.^does(Capture)>.

Captures and Parcels are also the basis for the multidimensionality of
lists in Perl 6. Unlike Perl 5, no flattening happens unless it's
explicitly required by the user, which is done by enforcing the list
context. If you use the item context the dimensionality should be
preserved.

In addition to the list and item context, there's also a special
context, which is, in a simplified way, called "Capture context", but
it actually means "deferred context", in a way that the Capture or
Parcel is kept as-is while they are manipulated in the code. This is
useful to avoid unwanted flattening as well as avoiding the DWIMmy
features that might change the capture's behavior.

This is the main point of why Capture and Parcel replace Perl 5
references, they allow you to send data untouched from one place to
another. The second reason is that as in Perl 6 everything is an
object, there isn't really "pass-by-value" anymore, you're always
sending a reference, Captures and Parcels simply carry other objects
without enforcing any context on them.

=head1 Capture or Parcel

While a C<Capture> is the object that holds the parameters sent to a
routine (positional and named), a C<Parcel> is a more fundamental data
structure that doesn't really differentiate named arguments from
positional arguments (but it still lets you access the named ones by
their name).

The basic underlying concept is that a Parcel behaves much like a
list, but it doesn't enforce any context, in a way that no flattening
or coercion is done. When you use the C<Positional> API on a Parcel, it
will include all the listed items, whether they look like named
arguments or positional arguments. For example:

  1, 2, :a<b>

The Parcel represented here has 3 positional items and allows you to
access the element 'a' through the C<Associative> interface. A Parcel
might be statically converted to a Capture if it's clear to the parser
that it's being used as the arguments to a routine call.

A Capture, on the other hand, is not required to keep the positional
information for the named arguments, for example:

  foo(1,:a<b>,2)

In the call to the routine foo, there are only two positional
arguments and one named argument, and you won't be able to find "b"
from the C<Positional> interface, but only from the Associative.

The differentiation from Parcel and Capture is important to keep the
regular use of inline declarations consistent, let's say you do the
following:

  my $a = (0, :a<b>, 2);
  say $a[2];

If we had Capture and Parcel as the same data structure, you wouldn't
get C<2> as the result of the above code, because there are only two
positional arguments, not three. Using the same example:

  sub foo($p1, $p2, :$a) {...}
  foo(|$a);

In that case, the Parcel is converted into a Capture, and therefore
the pair C<< :a<b> >> is no longer visible as a positional argument,
only as named.

Note that once you convert a Parcel into a Capture, you won't be able
to get the original Parcel again, because a Capture doesn't hold the
information about the position of named arguments.

=head1 Multidimensionality

Probably the most important task of Parcels and Captures is to
implement the multidimensionality of lists in Perl 6, this means that
the barrier used to detect the dimensionality of the data structures
by the operators is whatever the item inside it implements Parcel or
Capture. For instance:

  my $a = (1, (2, (3, 4)));
  say $a[1];

In that case, you'll get C<2, (3, 4)> (or whatever is implemented in
the .Str method of that specific Parcel). 

[Update:  The above (and much of what follows below) doesn't conform 
to the latest discussion on parcels; parcels flatten under item assignment. 
See L<http://irclog.perlgeek.de/perl6/2009-09-23#i_1532822>.]

But, you should be able to:

  say $a[1;0];

Which is going to return C<2>, which is almost the same as:

  say $a[1][0];

But the first provides a more convenient and optimizeable way of
asking for it. If you want to get the value C<4> from that data
structure you need to:

  say $a[1;1;1];

Note that if you assign that parcel to an array, it will be flattened,
so:

  my @a = 1, (2, (3, 4));
  say @a[3];

Would print C<4>, at the same time that trying to ask for
multidimensionality information from that list would result in a
failure:

  say @a[1;1;1];

As the element 1 of the array C<@a> is not a Capture or a Parcel, it is
not possible for the C<.[]> operator to traverse it.

[Conjecture: It is still not clear if the multidimensional access
should be able to get into regular arrays, i.e.: C<[1,[2,[3,[4]]]] ]>

It is important to realize that it's not the parens that are creating
the Parcel, but the C<< infix:<,> >>. The parens are only required in
order to define a sub-parcel.

On the other hand, if you bind a parcel to a variable, it doesn't
really matter which sigil it uses:

  my @a := (1, (2, (3, 4)));
  say @a[1;1;1]; # "4"
  say @a[3]; # failure

Captures and Parcels are seen the same way regarding
multidimensionality, for instance:

  my $a = ((map { $_ * 2 }, 1..5),(map { $_ / 2 }, 1..5));
  say $a[0;0]; # 2
  say $a[1;0]; # 0.5

The same way, if each map closure returns more than one item inside
its capture:

  my $a = ((map { $_ * 2, $_ / 2 }, 1..5),(map { $_ / 2, $_ * 2 }, 1..5));
  say $a[0;0;0]; # 2
  say $a[0;0;1]; # 0.5
  say $a[1;0;0]; # 0.5
  say $a[1;0;0]; # 2

The flattening process will traverse into Parcels and Captures, so:

  1, (2, (3, 4))

will result in:

  1, 2, 3, 4

after flattening, while:

  1, [2, [3, 4]]

Would remain as-is.

=head1 Context deferral

Also known as "Capture Context", defines how you can defer the context
coercion for a given value. That is a fundamental feature because
something as simple as assigning to a scalar might imply context
coercion that would get you a modified value.

Both the Parcel and the Capture are able to preserve the values as-is,
in a way that you can later apply any context and have the same result
as if the context was applied immediately.

Context deferral is actually the reason why Perl 6 no longer supports
the "wantarray" operator, nor does it provide any substitute. The way
you should implement wantarray-like behavior is by properly overriding
the coercion for each context. The Contextual::Return module is an
implementation of that concept in Perl 5.

In order to use the context deferral in your code, you need to use the
"capture sigil", which can be presented in two forms:

  my ¢a = (1, (2, (3, 4)));

or

  my @%a = (1, (2, (3, 4)));

The latter is provided as an alternative for situations where you want
to preserve the code in 7-bits only.

[Update: C<@%a> might not work out as a capture sigil -- 
See L<http://irclog.perlgeek.de/perl6/2009-09-21#i_1523801>.]

=head1 Additions

Please post errors and feedback to perl6-language.  If you are making
a general laundry list, please separate messages by topic.
