Group
Extension

Perl6-Pugs/docs/Perl6/FAQ/Capture.pod

=head1 NAME

Perl6::FAQ::Capture - Capture objects

=head1 DESCRIPTION

This FAQ answers questions about B<Capture> objects, as well as their uses in
bindings and function calls.

=head2 What

=head3 What happened to references?

They have been superseded by Capture objects.

=head3 What is a Capture?

A Capture is an object representing arguments in a function call.
More generally, Capture objects express annotated nodes with children
such as capture groups returned by rules, XML DOM nodes, argument lists
and more.

For example, the arguments in C<say("Hello", "World")> is a Capture
object denoted by C<\("Hello", "World")>.

=head2 How

=head3 Can I see what captures look like? Does \$x no longer work?

Prefix C<\> is now the Capture constructor.  These are all equivalent:

  my $xcap1 = \$x;
  my $xcap2 = \($x);
  my $xcap3 = \($x :);

All three represent an argument list with a single invocant C<$x>,
and hence are all equivalent with each other:

  $xcap1 === $xcap2 === $xcap3; # true

=head3 What about capturing multiple arguments?

Here's how Captures look like deferred argument lists:

  sub make_car (
    Str $model,
    Str $color? = "black",
    Int $doors  = 4
  ) { ... }

  # some positional, some named
  my $car_cap = \("Model T", doors => 2);

  # passing the opaque Capture as actual function arguments  
  my $car = make_car(|$car_cap);

  # extracting a specific positional argument
  say "The thing is $car_cap[0]"; # Model T
  
  # or by name
  say "It has $car_cap<doors> doors" # 2 doors

=head3 How do I extract all positional arguments or all named arguments?

As you can see above, a Capture object holds both positional and named
parts.  If you want to retrieve all positional parts, there are two ways:

  $cap[];  # postfix .[]
  @$cap;   # prefix @

Both forms flatten under list context, so they may be used
interchangeably.  However, only the postfix C<.[]> form interpolates in
a string.

Similarly, access to named arguments is available by treating the Capture
as a hash:

  $cap{};  # postfix .{}
  %$cap;   # prefix %

Note that the positional parts do not include the invocant.

=head3 What do you mean by "invocant"?

When you call an object's method, the C<self> inside the method is set
to that object. These are all equivalent:

  $fh.say("Hi!");
  say $fh: "Hi!";
  say($fh: "Hi!");

Note that an argument list can have at most one invocant. You can
construct a Capture object with an invocant using the same syntax:

  my $cap = \($fh: "Hi!");

To get back the invocant from a Capture object, use the prefix "$" operator:

  my $fh = $$cap;

So this Perl5ish equivalence still holds:

  $x === $(\$x);

=head3 What about multi-dispatch?

Multi-dispatch governs cases where multiple subroutines or methods share
the same name, relying on the arity and types of tie-breaking I<parameters>
in their parameter list (Signature):

    multi f ($x; $z)             { say 'A' }
    multi f (Int $x, Int $y; $z) { say 'B' }
    multi f (Str $x, Str $y; $z) { say 'C' }

    f(1, 2);            # goes to A
    f(1, 2, 3);         # goes to B
    f('x', 'y', 'z');   # goes to C

During multi-dispatch, a tie-breaking parameter may bind to the invocant
argument (e.g. for multi-methods), or one of the positional arguments.

However, regardless of single- or multi- dispatch, the argument list (Capture)
can never have more than one invocant.  Typically, the presence of an invocant
indicates a method-call (which may fall back to a subroutine-call); the lack of
invocant means a subroutine-call.

    1.foo(2);  # Int.foo with 1 as "self"; if not
               # found, fallback to foo(1, 2)
    foo(1: 2); # same as above

    bar(1, 2); # never looks at Int.bar; calls &bar
               # in lexical/package scope

Method/subroutine calls are determined by the presence of an invocant at the
calling site.  Single/multi dispatch are determined by the presence of "multi"
in the declaration site.  The two concepts are entirely orthogonal.

=head3 What happens when a named argument is repeated?

Let's look at some examples:

  sub make_car (Int $doors) {
    say "My car has $doors doors";
  }
  make_car(
    doors => 2, doors => 4
  ); # 4 doors
 
  sub board_ark (@animal) {
    say "@animal.elems() animals boarded the ark";
  }
  board_ark(
    animal => "moose", animal => "elephant"
  ); # 2 animals 

A Capture object may hold named arguments that occur twice or more.
When it's bound to a variable in the Signature, if the sigil is C<@>, then
it expands to a list of all arguments (in the order they were specified).

Otherwise (i.e. if it's bound to a scalar or a slurpy hash), the last
argument overrides the previous ones.

=head3 What do |$x, |@x and |%x mean?

The prefix C<|> operator casts objects into Captures, and merges them
t into the Capture currently being constructed (e.g. an argument list):

    my $cap = \(1, 2, x=>42);
    f(|$cap);   # f(1, 2, x=>42)

Array, List, Hash and Pair objects cast into Capture objects in obvious
ways:

    my $a = [1, 2];     f(|@$a);     # f(1, 2)
    my $l = (1, 2);     f(|@$l);     # f(1, 2)
    my $h = {x => 42};  f(|%$h);     # f(x => 42)
    my $p = (x => 42);  f(|%$p);     # f(x => 42)

It also works with C<@> and C<%> variables:

    my @a = (1, 2);     f(|@a);     # f(1, 2)
    my @a := [1, 2];    f(|@a);     # f(1, 2)
    my %h = (x => 42);  f(|%a);     # f(x => 42)
    my %h := {x => 42}; f(|%h);     # f(x => 42)


=head3 What does $x = \@y mean?

The same as C<$x = (@y: )>. That is, a Capture of one array as invocant. 

Unlike in Perl 5, this means that you can get back the Array object with:

  my @y2 := $$x; # get back the invocant

instead of:

  my @y2 := @$x; # WRONG: $x contains no positional parts

Manipulating the original value via the $x capture is still possible:

  $$x.push("another element");

Note the need for the extra $ sigil, implying we are accessing the
captured invocant.  C<@$x.push()> would mean an attempt to add an extra
positional argument into C<$x>; this would fail as all parts are immutable
in an Capture object.

(Captures are immutable; their underlying data may not be.)

=head3 So $x = @y does not mean $x = \@y anymore. Then, what does it mean?

It means assigning C<$x> with the object bound to C<@y> (typically an
Array object).

This does not create Capture objects; to get back C<@y>, C<@$x> would do.

Also note that all these forms mean the same thing:

  @y;
  @@y;
  @@@y;
  @y[];
  @y[][];
  @y[][][];

=head3 Does this mean I can't have something akin to a reference to a reference?

You can, as a Capture can contain another capture object in its invocant
slot:

    my $x = \\3;
    say $$$x; # same as "say 3"

=head3 Can I create a "pass-through" function that captures all arguments?

Yes, using the C<\$> signature:

    sub f (\$args) { g(|$args) }
    f(1, 2, x => 42);   # same as g(1, 2, x => 42)

The C<$args> above becomes a Capture object.

=head3 What about delegating a method?

Perl 6 has a few other provisions for this (e.g., .wrap), but if you want
more control over invocation, you can take advantage of the default Signature
for methods, which puts all positionals in C<@_> and named arguments in C<%_>:

  method front_meth {
    $!real_obj.back_meth( |<< @_, %_ );
  }

You can also take the argument list as a Capture object, and merge it with
another method invocation:

  method front_meth (\$args) {
    $!real_obj_A.back_meth( |$args );
  }

This works because when there is already an invocant present, further
invocants in the constructing argument list will be ignored.

=head3 How is @x = (1, 2, 3) different from @y := (1, 2, 3) ?

The latter is an error. :-)

The C<:=> operator binds its left hand side (a Signature object) to its
right hand side (a Capture object), so the latter form is akin to:

  sub foo (@y is rw) { ... }
  foo(1, 2, 3); # FAIL: three arguments passed where one is expected

However, these forms are valid:

  *@y := (1,2,3);         # slurpy @
  @y  := ((1,2,3):);      # list as invocant
  @y  := ((1,2,3),);      # list as first positional
  @y  := (y => (1,2,3));  # named binding

But they are still different from the assignment form.

=head3 How is @x = (1, 2, 3) different from *@y := (1, 2, 3), then?

This means that while C<@y> holds the values 1, 2, and 3, you cannot
modify the container itself, so this won't work:

  @y.push(4);   # FAIL: cannot find method: List.push

On the other hand, because variables are initialized by their sigils,
so these two mean the same:

  my @x := [];  # new Array object 
  my @x;        # implicitly does the same thing

so C<@x = (1, 2, 3)> would simply populate the previously allocated
Array object with new elements.

=head3 Is there any difference between $x = (1, 2, 3) and @y = (1, 2, 3)?

Yes.  The right-hand side in both case is a single List object constructed
with the list-associative C<< infix:<,> >> operator, but it is flattened
in the second case, and its elements are put into the previously allocated
Array container bound to C<@y>:

    $x.push(0); # FAIL: cannot find method: List.push
    @y.push(0); # works just fine

=head3 Is there any difference between $x = [1, 2, 3] and @y = [1, 2, 3]?

Yes.  As in Perl 5, the Array constructor C<circumfix:[ ]> does not
flatten under list context, so C<@y> receives a List with one element
(an Array object), which then becomes C<@y[0]>:

    $x.elems; # 3
    @y.elems; # 1

The cases below are similar to Perl 5 as well:

    $x.push(0);     # works - $x.elems becomes 4
    @y[0].push(0);  # works - @y.elems remains 1
    @y.push(0);     # works - @y.elems becomes 2 

=head3 Is there any difference between $x := [1, 2, 3] and @y := [1, 2, 3]?

For the usual method-based operations, they are pretty much interchangeable:

    $x.push(0); # works - $x.elems becomes 4
    @y.push(0); # works - @y.elems becomes 4

However, they differ when you try to assign something into them:

    $x = 42; # FAIL  - Array doesn't handle scalar assignment
    @y = 42; # works - @y.elems is now 1

Note that C<$x = 42> fails because the C<:=> in C<$x := [1, 2, 3]>
changes the underlying container of $x from a Scalar into an Array.
Compare this with the assignment case:

    $x = [1,2,3];
    $x = 42;        # works just fine

and also binding into an integer:

    $x := 41;
    $x = 42;        # FAIL - Int doesn't handle scalar assignment either

=head3 So how do Captures work with Rules?

In the context of rules, Captures are superclasses of Match. So in the example of:
    
    my $rv = ("x-y-z-moose" ~~ /(.)-(.)-(.)-<animal> :{ return give_birth(|$/) })

C<give_birth()> gets called with 'x', 'y', and 'z' as positional arguments,
and :animal<moose> as a named argument.  C<give_birth()> can return a Moose object -
and C<$rv> is assigned a Capture object with the Moose object in its invocant slot.
C<$rv> has the same positional and named slots as the Moose object - and you can
retrieve the Moose back through C<$rv as Animal>.

Nested captures in the rule then become nested Capture objects within positional
slots in $/, which allows them to be retrieved as arguments for additional functions.
And so you can bind annotated nodes of a tree to particular function calls, passing
the data straight in thanks to the equivalence of Captures returned by rules and
Captures used to invoke functions and methods.  As such, Captures could be considered
a natural data type for XML nodes, and provide considerable power for parsing DOMs using
Rules, and providing native tree manipulations.


=head2 Why

=head3 What prompted this change? Was there something innately lacking in refrences?

[needs beefing up.]

* references lose form and type

* Capture also does most of what globs did, but in a safer and saner manner

* the concept of Capture is applicable in match results


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.