Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Re^2: multiple method calls against the same object, revisited

by Aristotle (Chancellor)
on Dec 28, 2004 at 09:51 UTC ( #417733=note: print w/replies, xml ) Need Help??

in reply to Re: multiple method calls against the same object, revisited
in thread multiple method calls against the same object, revisited

Ugh. :-( Sorry, but I'm not going to be sticking stuff in UNIVERSAL:: willy nilly, particularly not to fix such a trivial complaint. You could put it in a different package and call it as in ->UTIL::invoke_methods() or something.

In terms of parameter format, your code is quite similar to my first attempt at multiple method calls against the same object (f.ex GUI programming). Putting the method name outside the list of parameters but it's awkward rather than convenient in practice. In my code I did it because I wanted to be able to represent sub-callchains as in

$obj->foo; $obj->child->bar; $obj->baz;

but it's still too limited anyway because you can't pass parameters to intermediate methods. Putting the methodname inside the arrayref actually allows for syntax to handle this. (You put nested arrayrefs in front of the name of the method to call, easily distinguished because the name must be a string.)

Another option might be something like

sub CHAIN::AUTOLOAD { my $self = shift; my ( $method ) = ( our $AUTOLOAD =~ /.*::(.*)/ ); $self->$method( @_ ); $self; } # now we can say my $window = Gtk2::Window ->new( "toplevel" ) ->CHAIN::signal_connect( delete_event => sub { Gtk2->main_quit } ) ->CHAIN::set_title( "Test" ) ->CHAIN::set_border_width( 15 ), ->CHAIN::add( Gtk2::Button ->new( "Quit" ) ->CHAIN::signal_connect( clicked => sub { Gtk2->main_quit } ) ) ->CHAIN::show_all();

but again, ugh.

Trust me, I've been around the block a number of times with this one. All of the “solutions” suck, the one in the root node just IMHO sucks a little less than all the others. We need Perl6.

Update: oh, and thanks for the heads up on $@!

Makeshifts last the longest.

Replies are listed 'Best First'.
Re^3: multiple method calls against the same object, revisited
by eric256 (Parson) on Dec 28, 2004 at 18:33 UTC

    Here is a similar solution inspired by your code.

    package Chain; sub new { my $proto = shift; my $self = {obj => shift}; bless $self, $proto; return $self; } sub AUTOLOAD { my $self = shift; my ( $method ) = ( our $AUTOLOAD =~ /.*::(.*)/ ); $self->{obj}->$method( @_ ); $self; } 1;

    Now we can just do Chain->new($obj) and call methods on that object expecting the object itself as a return. I'm sure this could be cleaned up to handle errors etc.

    use strict; use warnings; use lib "."; use Chain; use Test; my $t = new Test; $t->hello; $t->cool(1,2); Chain->new($t) ->test ->hell(1,2,3) ->say("hello");

    Eric Hodges

      Yeah, you pretty much just wrote what I did in RFC: Class::Proxy::MethodChain. Now make a root node about it, get some well-reasoned skeptic comments, mull over it for a year or so, and then write the code I posted in the root node of this thread. :-) As I said, I've gone through at least a dozen approaches and logical next steps with this thing and it's not likely you'll be able to surprise me as long as you stick to the obvious ideas — sorry.

      The problem with this group of solutions, as others said in that thread and as I have come to understand with the experience gained since that node (see Mutator chaining considered harmful), is that method chaining is not a good idea.

      Makeshifts last the longest.

        Well it wasn't realy meant as an end all solution, thought its growing on me. It is not an area I claim either expertise or experience. ;) BTW isn't method chaining (the way I handled it here) the same as your multiple methods? I'm not messing with the class or anything, just proxying along. Either way i think you've got a cool idea and i can't wait to play with it in Perl 6 in X years. ;)

        Eric Hodges
      How is this a gain over Class::Null? For more info, take a look at The Null Mull (or, when OO needs more O)

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        I'm sorry I don't see how this even compares to that. The function of this is to wrap methods so that they always return a reference to the object. The Class::Null make an object that handles all method calls gracefully. I don't see how the two are related other than they pertain to method chaining, however they deal with different parts, this wraps the method call to force it to chain, that wraps it to handle error cases. The two could be combined to supply some extra method chaining sugar though.

        Eric Hodges

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://417733]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2021-04-17 14:52 GMT
Find Nodes?
    Voting Booth?

    No recent polls found