Perl 6
SMOP Capture Expansion: Revision 4


Capture expansion means taking different objects and using them as part of the actual capture of a call. That means that the number of positional arguments, as well as the set of named arguments might not be determined at compile time.

The syntax for that is:

  bar(|$capture_object, |@positional_arguments, |%named_arguments)

The prefix:<|> operator implies "Capture" context, which in SMOP means a .Capture() call. This is needed so that

my $a = (1,2,3);

works as expected. When you do

my $a = \(1,2,3);

It creates a capture object at the first line, and the capture object then return itself in the "capture context".

Mixing several captures

When mixing different capture objects, the positional argument order must be preserved and named arguments conflict should raise warnings. Additionally, the mixing of inline arguments with capture expansion should produce other capture objects that will then be mixed together...

 bar($a, |$b, $c, |@d, :foo<bar>, $e, |%f)

In that case, in order to preserve positional order, as well as preserve the priority on named arguments definition (the last overwrite the first, raising a warning), we need to actually create 6 different capture objects and mix them in the correct order:

 my $c1 = \($a);
 my $c2 = \($c);
 my $c3 = \(:foo<bar>, $e);
 bar(|$c1, |$b, |$c2, |@d, |$c3, |%f)

Capture Merger Object

In order to avoid making copies of all the arguments in all the inner captures, the "Capture Merger" object will hold references to all the inner capture objects and proxy to that information, making sure the context propagation happens as late as possible.

Capture Merger API

class CaptureMerger {
 has @.captures;

 method elems {
   [+] @.captures.elems;

 method postcircumfix:<[ ]> ($index) {
   -> $merger, $capture, $offset {
     fail('Non-existant positional argument') if $capture >= $merger.captures.elems;
     $merger.captures[$capture].elems > $offset ??
       &?BLOCK($merger, $capture + 1, $offset - $merger.captures[$capture].elems) !!
   }(self, 0, $index);

 method postcircumfix:<{ }> ($key) {
   -> $merger, $capture {
     fail('Non-existant named argument') if $capture < 0;
     $merger.captures[$capture].:exists($key) ??
     $merger.captures[$capture]{$key} !!
     &?BLOCK($merger, $capture - 1);
   }(self, $.captures.elems - 1);


Upload Files

Click "Browse" to find the file you want to upload. When you click "Upload file" your file will be uploaded and added to the list of attachments for this page.

Maximum file size: 50MB

File Name Author Date Uploaded Size

Save Page As

Enter a meaningful and distinctive title for your page.

Page Title:

Tip: You'll be able to find this page later by using the title you choose.

Page Already Exists

There is already a page named XXX. Would you like to:

Save with a different name:

Save the page with the name "XXX"

Append your text to the bottom of the existing page named: "XXX"

Upload Files

Click "Browse" to find the file you want to upload. When you click "Add file" this file will be added to the list of attachments for this page, and uploaded when you save the page.

Add Tags

Enter a tag and click "Add tag". The tag will be saved when you save the page.