$object->method1(@args1)->method2(@args2)->method3(@args3) #### $chain = Object::MethodChain->method1(@args1)->method2(@args2)->method3(@args3); #### $chain = Object::MethodChain->new("method1", \@args1, "method2", \@args2, "method3"); #### $chain = Object::MethodCall->method1(@args1)->method2(@args2); #### Object::MethodCall->method1(@args1) #### { package Object::MethodChain; use overload q[""], "__Set_MethodChain__"; AUTOLOAD { my $self = shift; my $class = ref($self) || $self; my @new = ref($self) ? @$self : (); our $AUTOLOAD =~ /.*::(.*)/s or die "error: invalid method name"; push @new, {"method", $1, "args", \@_}; bless \@new, $class; } our $chain; sub __Set_MethodChain__ { $chain = $_[0]; "__Call_MethodChain__"; } sub UNIVERSAL::__Call_MethodChain__ { my $r = $_[0]; for my $pair (@$chain) { my($method, $args) = @$pair{"method", "args"}; $r = $r->$method(@$args); } $r; } DESTROY { } } #### { package Object::MethodChain; AUTOLOAD { my $s = shift; my $c = ref($s) || $s; my $p = ref($s) ? $s : sub { $_[0] }; our $AUTOLOAD =~ /.*::(.*)/s or die; my $m = $1; my $a = \@_; bless sub { &$p($_[0])->$m(@$a); }, $c; } DESTROY { } } #### $chain = Object::MethodChain->foo; #### sub { $_[0]->foo; } #### { package Object::MethodChain; our $open_sesame = []; AUTOLOAD { my $self = shift; my $class = ref($self) || $self; my @chain = ref($self) ? &$self($open_sesame) : (); our $AUTOLOAD =~ /.*::(.*)/s or die "error: invalid method name"; push @chain, {"method", $1, "args", \@_}; bless sub { if(ref($_[0]) && $open_sesame == $_[0]) { @chain; } else { my $r = $_[0]; for my $pair (@chain) { my($method, $args) = @$pair{"method", "args"}; $r = $r->$method(@$args); } $r; } }, $class; } DESTROY { } } #### { package Object::MethodChain; use overload q[""], "__Set_MethodChain__"; AUTOLOAD { my $self = shift; my $class = ref($self) || $self; my @new = ref($self) ? @$self : (); our $AUTOLOAD =~ /.*::(.*)/s or die "error: invalid method name"; push @new, {"method", $1, "args", \@_}; bless \@new, $class; } our $chain; sub __Set_MethodChain__ { $chain = $_[0]; "Object::MethodChain::__Call_MethodChain__"; } sub __Call_MethodChain__ { my $r = $_[0]; for my $pair (@$chain) { my($method, $args) = @$pair{"method", "args"}; $r = $r->$method(@$args); } $r; } DESTROY { } } #### { package AnObj; sub new { bless [], $_[0]; } sub foo { print "just "; $_[0]; } sub bar { $_[1] = "ack"; OtherObj->new("erl h"); } } { package OtherObj; sub new { bless [$_[1]], $_[0]; } sub baz { print "anot", $_[1], $_[0][0]; "er,\n"; } } #### { my $f = "foo"; my $n = AnObj->new->$f->bar(my $v)->baz("her p"); print $v, $n; } #### { my $f = "foo"; my $c = Object::MethodChain->new->$f->bar(my $v)->baz("her p"); my $n = AnObj->$c; print $v, $n; } #### { my $f = "foo"; my $m = Object::MethodChain->$f->bar(my $v); my $c = Object::MethodChain->new->$m->baz("her p"); my $n = AnObj->$c; print $v, $n; } #### bless( [ { 'args' => [], 'method' => 'new' }, { 'args' => [], 'method' => 'foo' }, { 'args' => [ undef ], 'method' => 'bar' }, { 'args' => [ 'her p' ], 'method' => 'baz' } ], 'Object::MethodChain' );