CoroはCoroutineのCoro - PerlでFiber

Ruby勉強会@関西でFiberについて勉強してきた - はこべブログ ♨でPerlでもGeneratorをうまく書けるモジュールがないかなーとこぼしていたところ.

perlではCoroでほぼ同じ事ができるが、どちらにしろCoroを使う利点は1個1個をresumeすることじゃなくて 非同期に実装することだと思うのでgenerator云々はちょっと用途が違う気もするです

http://b.hatena.ne.jp/lestrrat/20090202#bookmark-11922880

というブコメをいただきました.id:lestrratさんありがとうございます.

Coroについて調べてみたところ,Coro::Introによると

The natural application for these is to include a scheduler, resulting in cooperative threads, which is the main use case for Coro today.

とあって,やはり,スケジューリングなどもおこなう,コルーチンよりずいぶん高機能なものになっているみたいです.ただし,

Coro started as a simple module that implemented a specific form of first class continuations called Coroutines.
...
This is nowadays known as a Coro::State.

とあるように,もともと持っていた純粋なコルーチンの機能はCoro::Stateというモジュールで実現できるようです.

Coro::Stateにはコルーチンをきりかえるtransferというメソッドが用意されているのですが,このメソッドはRuby1.9のFiberのyieldのように値を返すことができません.コルーチン切り替え時の値は別に記録しておく必要があります.このあたりを注意して,以下のようにGeneratorを実装してみました.

56803’s gists · GitHub
yieldで値を返せないぶん一つ余計にクロージャが必要になっているので,ちょっとくどいコードになってます.しかし,ここはPerlというかCPANというか,このコードをうまくラッピングしてくれるモジュールであるCoro::Generatorがありました.

Coro::Generatorを利用すると,同じコードが以下のように書けます.

coro_generator.pl · GitHub
ずいぶんコードの意図がわかりやすくなりました.

というわけで,RubyのFiberと同じようなことがしたければ,PerlではCoroを使えってことですね.Coro自体はコルーチンの実現以外に並列処理を簡単に書ける仕組みがいろいろあって便利そうなので,うまく使えるとかっこよいですね.