我想了解下面perl脚本执行的每一步发生了什么,我的意思是,我知道变量,散列,整数数组是什么,但我不知道它们是如何在这个使用惰性评估的powerset结构中相互作用的。我还想知道哪些因素决定了sub powerset(&@)
子程序的进度是哪一步。例如,我想从第六个子集开始打印,而不是第一个子集,那么我应该替换哪些变量的哪些值?
use strict;
use warnings;
sub powerset(&@) {
my $callback = shift;
my $bitmask = '';
my $bytes = @_/8;
{
my @indices = grep vec($bitmask, $_, 1), 0..$#_;
$callback->( @_[@indices] );
++vec($bitmask, $_, 8) and last for 0 .. $bytes;
redo if @indices != @_;
}
}
powerset { print "[@_]n" } 1..21;
my $bytes = @_/8;
:这里@_
是数组输入参数,所以@_ = 1..21
,当在标量上下文中计算时,它返回数组的长度。所以$bytes = 21/8 = 2.625
my @indices = grep vec($bitmask, $_, 1), 0..$#_;
这里$#_
是@_
的最后一个索引,是20。因此,在数组0..20
上运行grep。对于数组中的每个元素,检查$bitmask
中是否设置了相应的位值,如果设置了则保存在@indices
数组中。$callback->( @_[@indices] );
:调用回调函数的索引数组对应于$bitmask
中设置的位。由于$bitmask
最初是空的,在第一次迭代中,@indices
将等于空数组[]
。++vec($bitmask, $_, 8) and last for 0 .. $bytes;
:从0..由于$bytes == 2.625
,它被舍入到最接近的整数值。对于0..2
中的每个字节索引值,$bitmask
中相应的字节(现在被视为字节数组)递增。新的字节值从vec
返回,如果返回值非零,for循环退出(由于and last
部分)。但是,如果字节的值为255,则++vec($bitmask, $_, 8)
将返回0(字节值绕到0),并且for 0..$bytes
for
循环的下一次迭代将执行。 如果
@indices
数组的长度不同于@_
数组的长度(即:21),则redo if @indices != @_;
再次运行块(第7-12行)。