是否有任何 Perl API 可以让我在读取数组元素时执行代码?我在想类似的东西(或者也许可以?)Variable::Magic,我该怎么做?最终目标是本质上重新计算任何访问(延迟评估)的元素值,但我不想将 , 之类的函数限制grep
为map
不可natatime
用。
3 回答
CPAN 上有几个用于惰性数组的模块。 Data::Lazy、Variable::Lazy、Tie::Array::Lazy和Variable::Magic。
Data::Lazy 和 Tie::Array::Lazy 都打成平手。绑定非常慢,比普通数组慢约 10 倍,比对象慢约 3 倍。捆绑可能会扼杀懒惰的性能优势。
变量::懒惰是不同的。它实际上是在编译时使用 Devel::Declare 魔法将变量替换为一大段代码。不幸的是,它似乎只适用于标量。:-/
变量::魔法是……魔法。它更多地用于注释变量而不是控制它们。
我建议改为反转问题。将事物写成一个可以随心所欲地懒惰的对象。与领带相比,这更快、更灵活、可能更具特色且错误更少。对于 grep、map 等,提供一个重载它以便它可以用作数组 ref。重载不会是懒惰的,但是 grep 和 map 无论如何都必须在整个列表上工作,并且 tie 不会对你有任何好处。并且对象可能能够提供更高效的搜索和变换方法。
惰性列表是我们List::Gen
的强项之一。
您可能会发现 brian d foy 的这篇文章很有用:http ://www.effectiveperlprogramming.com/blog/300 。特别是这段代码对和(无限)绑定数组进行惰性求值。
use 5.012;
{
package Tie::Array::InfiniteSquares;
use parent qw(Tie::Array);
use Carp qw(carp);
use Config qw(%Config);
# mandatory methods
sub TIEARRAY {
bless {}, $_[0];
}
sub FETCH {
my( $self, $index ) = @_;
$index ** 2;
}
sub FETCHSIZE { 0x7F_FF_FF_FF } # still problems here
sub STORE { carp "You can't touch this!" }
sub STORESIZE { carp "You can't touch this!" }
sub EXISTS { 1 }
sub DELETE { carp "You can't touch this!" }
}
tie my @array, 'Tie::Array::InfiniteSquares';
while( my( $index, $value ) = each @array )
{
say "Item is $value at index $index";
}
现在假设您的实际数据集不是无限的,那么当您正确构建绑定类时,您可以each
进行惰性评估。map
, grep
,for
等会在行动之前评估整个列表,但它们仍然可以工作。