Attribute::Generator - Perlでジェネレータを作りたい!

Pythonにジェネレータって仕組みがありますね。 簡単に言うと、「値を返しつつ、途中から再開出来る関数」。 ジェネレータを実行すると、イテレータを返して、それに対してnextメソッドを呼ぶ度に 次の yield まで進んで、yieldの引数を nextの返値として返してくれます。

そういうのをPerlでやりたくて、 Iterator::Simple とかを作ってたのですが、 実行状態の保存をクロージャで自前実装しなきゃいけなかったりで、結構めんどう でした。

なんとなく解決出来そうな気がしたので、勢いで実装して Attribute::Generator というモジュールをCodeReposに上げました

使い方は簡単。適当な関数にGeneratorアトリビュートつけて、 その中で yield 呼ぶだけです。

use Attribute::Generator;

sub fib:Generator {
  my($x, $y) = (0, 1);
  while(1) {
    yield $y;
    ($x, $y) = ($y, $x+$y);
  }
}

まず。fib() を実行してイテレータを得ます。

my $iter = fib();

あとは $iter->next する度に、1, 1, 2, 3, 5, 8, 13, 21, 34, ... と値を返してきます。 Iterator::Simpleと違って、yieldの直後から再開します。whileの途中からでも問題ありません。 クロージャでごにょごにょする必要もありません。

しかし・・・

遅いです(泣)。うちの環境で 50 万回 next 呼ぶのに 7秒くらいかかります。 こういうのって、メモリに乗り切らないくらい大量のデータを一つ一つ処理したい時に 使うことが多いのに、これでは使いものになりません(泣)

バックエンドに Coro::State というモジュール使って、関数の実行状態を保存しつつ メインロジックと行ったり来たりして実装してるのですが、そのスイッチに時間がかかるみたい。

どうしようもないかなー。誰か助けてください><

Coro::State については、また今度書けたら書きます。

トラックバック(0)

このブログ記事を参照しているブログ一覧: Attribute::Generator - Perlでジェネレータを作りたい!

このブログ記事に対するトラックバックURL: http://www.fs-output.com/rintaro/mt/mt-tb.cgi/28

コメントする

(初めてコメントする場合、承認されるまではコメントが表示されない場合があります。)

このブログ記事について

このページは、Rintaroが2008年11月 5日 18:03に書いたブログ記事です。

ひとつ前のブログ記事は「クラスメソッドのインポート」です。

次のブログ記事は「Coro::State - 現在の実行状態を保存しておける箱」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.0rc4