像Slurpy一样使用Capture

问题描述 投票:8回答:1

我一直在读关于Captures的内容,这一段引起了我的兴趣:

在签名内部,可以通过在sigilless参数前加上垂直条|来创建Capture。这会将参数列表的其余部分打包到该参数中。

这听起来很像**@(非扁平化)邋,,所以这个编制了这个测试代码:

my $limit=1_000_000;
my @a=1 xx 10000;
my @b=-1 xx 10000;

sub test1(|c){
    1;
};

sub test2(**@c){
    1;
};
{ 
    for ^$limit {
        test1(@b,@a);
    }
    say now - ENTER now;
}
{
    for ^$limit {
        test2(@b,@a);
    }
    say now - ENTER now;
}

示例运行给出每个测试块的持续时间:

0.82560328                                                                                                                                                                                                                                                                                                         
2.6650674 

Capture肯定具有性能优势。以这种方式使用Capture作为一种邋??是否有不利的一面?我是否简化了比较?

capture perl6
1个回答
10
投票

Capture有两个插槽,包含VM级数组(位置参数)和散列(命名参数)。它的结构非常便宜,并且 - 由于|c风格的论证在内部的各个部分非常普遍 - 已经得到了很好的优化。由于捕获参数会覆盖位置参数和命名参数,因此将以静默方式忽略任何命名参数。对于方法而言,这可能不是什么问题,其中不需要的命名参数无论如何都将被静默放置到%_中,但如果在sub上使用此构造,则可能需要考虑,因为它不是纯粹的优化:它会改变行为。

**@c案例分配了一个Array,然后为每个传递的值分配一个Scalar容器,将它们放入Scalar容器中,并将那些Scalar容器放入Array中。这是一项合理的额外工作。

这里没有考虑另一个案例,就是这个案例:

sub test3(**@c is raw){
    1;
}

这将List放置在@c中,并将其元素设置为直接引用所传递的内容。这比没有is raw的情况便宜一点。从理论上讲,它可能表现得和|c这样的捕获参数一样好 - 如果不是更好的话。它可能只是需要有人在编译器上进行深入研究它为什么还没有。

总而言之,如果不关心强制执行项目化和/或有一个可变的Array传入参数,那么添加is raw可能是一个比选择一个捕获参数更好的优化赌注:参数处理语义更接近,它已经快一点,将允许对于更自然的代码,并且未来有可能像|c一样快,如果不是更快。

© www.soinside.com 2019 - 2024. All rights reserved.