为什么高阶Perl的make_rand不起作用?

时间:2015-12-28 19:24:00

标签: perl iterator

我试图从HOP中获取此迭代器代码:

# code from HOP p.156
sub make_rand {
my $seed = shift || (time & 0x7fff);
return Iterator 
    {   $seed = (29*$seed+11111) & 0x7fff;
        return $seed; 
    }
}

# code adapted from HOP p.157
my $rng = make_rand(1);
while (<>) {    
#   my $random = NEXTVAL($rng); # original code from HOP, adapted as next line
    my $random = $rng->();  # this treats $rng as a number, not as a ref to a sub
    print "\nrandom=$random";
}

如上所述,$ rng作为Number返回,而不是Iterator的ref,因此当我尝试取消引用它时,它会在倒数第二行中出错。

我应该为NEXTVAL使用不同的表格吗?

如果我单独定义子迭代器,程序工作正常,例如:

sub make_rand {
  my $seed = shift || (time & 0x7fff);
  return Iterator($seed);
}
sub Iterator {
    my $seed = shift;
    $seed = (29*$seed+11111) & 0x7fff;
    return $seed;
  }

#main
my $random = make_rand(1);
print "\nat42: random=$random";

while (<>) 
{   $random = Iterator($random);
    print "\nat48: random=$random";
}

1 个答案:

答案 0 :(得分:7)

您需要book's code附带的文件Iterator_Utils.pm,因此您可以use Iterator_Utils qw(Iterator),或者将Iterator子例程的定义插入到您自己的代码中,之后任何对Iterator¹的调用:

sub Iterator (&) { return $_[0] }

或者,由于这只是clever way允许您编写Interator { ... }来声明没有sub关键字的匿名子例程,因此您可以将Iterator替换为{{} 1}}它会起作用。

[1]这是使用原型声明子例程的众多缺点之一。因为原型告诉解析器如何解释原型子程序调用,所以原型声明必须在文件中比调用本身更早出现。