使用惰性求值的 perl 脚本说明

explanation of perl script using lazy evaluation

我想了解下面执行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 并且在标量上下文中计算时,它 return 是数组的长度。所以$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..2 开始循环,因为 $bytes == 2.625 它向下舍入到最接近的整数值。对于 0..2 中的每个字节索引值,$bitmask 中的相应字节(现在被视为字节数组)递增。新的字节值是 returned 从 vec,如果 returned 值是非零的 for 循环退出(由于 and last 部分。但是,如果值字节为 255,++vec($bitmask, $_, 8) 将 return 为 0(字节值环绕为零),for 0..$bytes for 循环的下一次迭代将执行。
  • 如果 @indices 数组的长度不同于 @_ 的长度(即:21),
  • redo if @indices != @_; 再次运行块(第 7-12 行)。