めも:Sub::Future
継続を使わない場合のget_multiのまとめ方を検討している。
これから、〜〜するぞ!という状態のオブジェクト。つまり継続もどき。
sub hoge { my $self = shift my $cache = $self->get_cache;# この手前で処理を停止させたい if( defined $cache ){ return $cache; } my $db = $self->get_from_rpc;# この手前で処理を停止させたい $self->set_cache($db); return $db; }
こんなかんじのロジックを次のように組み替え。
sub hoge_future { my $self = shift; return future( $self,q<get_cache>,sub{ my $cache = shift; if( defined $cache ){ return $cache; } return future($self,q<get_from_rpc>,sub{ my $db = shift; set_cache($db); return $db; }); }); }
そうすると、
::is $self->hoge,$self->hoge_future->next->next;
二つが等価になる。
止めたいところでとめて、何をしようとしているのかわかるので、
それをあつめてget_multiしたりbulk_loadしたりできる。
my $memfuture = $self->hoge_future->next; my ($mem,$key) = @{ $memfuture->binded }; my $r = Memcached->get($key); $memfuture->next_with($r);
package Sub::Future; use strict; use warnings; use Scalar::Util qw/blessed/; use Data::Util qw/is_instance/; use base qw/Class::Accessor::Fast Exporter/; __PACKAGE__->mk_accessors(qw/function binded callback class_name method_name/); our @EXPORT = qw//; our @EXPORT_OK = qw/future/; sub future { my $self = shift; my $method = shift; my $callback = pop; my @args = @_; return Sub::Future->new( { binded => [ $self, @args ], class_name => blessed $self ? ref $self : $self, method_name => $method, function => $self->can($method), callback => $callback } ); } sub next { my ($self) = @_; my @binded = @{ $self->binded }; my $func = $self->function; return $self->next_with($func->(@binded)); } sub next_with{ my ($self,$result) = @_; return $self->callback->($result); } sub run{ my ($class,$future) = @_; my $value = $future; while( is_instance( $value,$class) ){ $value = $value->next; } return $value; } 1;