<?xml version="1.0" encoding="UTF-8"?>

<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule">

<channel>
<title><![CDATA[Perl 6: SMOP Capture Expansion]]></title>
<link>http://www.perlfoundation.org/perl6/index.cgi?smop_capture_expansion</link>
<description></description>
<pubDate>Fri, 29 Aug 2008 19:17:06 -0000</pubDate>
<webMaster>synedra@gmail.com</webMaster>
<generator>Socialtext Workspace v2.14.7.2</generator>

<item>
<title><![CDATA[SMOP Capture Expansion]]></title>
<link>http://www.perlfoundation.org/perl6/index.cgi?smop_capture_expansion</link>
<description><![CDATA[<div class="wiki">
<h1 id="basics">Basics</h1>
<p>
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.</p>
<p>
The syntax for that is:</p>
<pre>
  bar(|$capture_object, |@positional_arguments, |%named_arguments)
</pre>
<br /><p>
The prefix:&lt;|&gt; operator implies &quot;Capture&quot; context, which in SMOP means a .Capture() call. This is needed so that</p>
<pre>
my $a = (1,2,3);
foo(|$a);
</pre>
<br /><p>
works as expected. When you do</p>
<pre>
my $a = \(1,2,3);
foo(|$a);
</pre>
<br /><p>
It creates a capture object at the first line, and the capture object then return itself in the &quot;capture context&quot;.</p>
<h1 id="mixing_several_captures">Mixing several captures</h1>
<p>
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...</p>
<pre>
 bar($a, |$b, $c, |@d, :foo&lt;bar&gt;, $e, |%f)
</pre>
<br /><p>
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:</p>
<pre>
 my $c1 = \($a);
 my $c2 = \($c);
 my $c3 = \(:foo&lt;bar&gt;, $e);
 bar(|$c1, |$b, |$c2, |@d, |$c3, |%f)
</pre>
<br /><h1 id="capture_merger_object">Capture Merger Object</h1>
<p>
In order to avoid making copies of all the arguments in all the inner captures, the &quot;Capture Merger&quot; 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.</p>
<h2 id="capture_merger_api">Capture Merger API</h2>
<pre>
class CaptureMerger {
 has @.captures;

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

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

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

}

</pre>
</div>
]]></description>
<author>Daniel Ruoso</author>
<guid isPermaLink="true">http://www.perlfoundation.org/perl6/index.cgi?smop_capture_expansion</guid>
<pubDate>Fri, 29 Aug 2008 19:17:06 -0000</pubDate>
</item>

</channel>
</rss>