解释perl脚本使用延迟求值



我想了解下面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..$bytesfor循环的下一次迭代将执行。
  • 如果@indices数组的长度不同于@_数组的长度(即:21),则redo if @indices != @_;再次运行块(第7-12行)。

最新更新