配列要素の読み取り時にコードを実行できるPerlAPIはありますか?私は次のようなことを考えています(または多分それはできますか?)Variable :: Magicそして私はそれをどのように行うでしょうか?最終的な目的は、基本的にすべてのアクセスで要素値を再計算することです(遅延評価)が、、、などの関数を使用できないようgrep
に制約したくありません。map
natatime
3 に答える
CPAN には、遅延配列用のモジュールがいくつかあります。 Data::Lazy、Variable::Lazy、Tie::Array::Lazy、およびVariable::Magic。
Data::Lazy と Tie::Array::Lazy はどちらも同順位です。タイイングは非常に遅く、通常の配列よりも約 10 倍遅く、オブジェクトよりも約 3 倍遅くなります。結合すると、遅延によるパフォーマンスの利点が失われる可能性があります。
Variable::Lazy は違います。実際には、Devel::Declare マジックを使用して、コンパイル時に変数をコードのチャンクに置き換えます。残念ながら、スカラーでのみ機能するようです。:-/
変数::魔法は... 魔法です。変数を制御するよりも、変数に注釈を付けるためのものです。
代わりに、問題を逆にすることをお勧めします。好きなだけ怠惰にできるオブジェクトとして物事を書きます。これは、ネクタイよりも高速で、柔軟性があり、機能が豊富で、バグが少ない可能性があります。grep、map などの場合は、オーバーロードを提供して、配列参照として使用できるようにします。オーバーロードは怠惰ではありませんが、とにかく grep と map はリスト全体で機能する必要があり、tie はそれ以上の効果はありません。また、オブジェクトは、より効率的な検索および変換メソッドを提供できる場合があります。
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
動作する前にリスト全体を評価しますが、それでも機能します。
遅延リストはList::Gen
の強みの 1 つです。