http://www.perlmonks.org?node_id=237731


in reply to RFC: Class::Proxy::MethodChain

Obviously if it works for you - go for it ;-)

However, personally, I don't like it and find it the examples you've shown more opaque than the originals.

I understand what you're trying to do, but I would personally use for where I can and live with the API where I cannot. For me the various calls to MethodChain obscure more than they clarify.

Sorry :-/

Replies are listed 'Best First'.
Re^2: RFC: Class::Proxy::MethodChain
by Aristotle (Chancellor) on Feb 22, 2003 at 15:42 UTC

    My beef with for (which I like a lot) in this case is that it necessitates weaving calls against different objects into a single block..

    I can see why people are saying the syntax C::P::MC produces looks more opaque. I think it's a matter of getting used to, and one of style.

    I was discussing this with Juerd yesterday. He made the point that once you set up a method to return $self natively, you can never again change that method to return something else should the need arise in future. That sounded like a very good argument to me, and I countered that intentionally outsourcing method chaining to something like C::P::MC instead of doing it natively would actually allow anyone to choose which style they prefer, for any class, at any one moment, to which he agreed. We also agreed that it's mostly a matter of style and taste - he said chaining didn't really appeal to him.

    So I guess this is really a matter of just going ahead and waiting for feedback from people who (try to) use it.

    Makeshifts last the longest.

      I basically agree :-) There are certainly other useful styles for setters. For example, the idiom of returning the old value in a setter allows you to compact:

      my $old = $foo->fribble $foo->fribble($new); ... do something ... $foo->fribble($old);

      to

      my $old = $foo->fribble($new) ... do something; $foo->fribble($old);

      However, for me the extra clutter that C::P::MC adds takes away the advantages that chaining gives you :-)

      That said - how about this as a way to get around the name clashing problems:

      package Class::Chain; use strict; use warnings; sub AUTOLOAD { my $self = shift; our $AUTOLOAD; my ($method) = ($AUTOLOAD =~ m/^.*::(.*)$/); return bless \$self->$method(@_) unless ref($self); return $$self->$1(@_) if $method =~ m/^raw_(.*)$/; return bless \$$self->$1(@_) if $method =~ m/^wrap_(.*)$/; $$self->$method(@_); return($self); }; sub chain { my ($self, $sub) = @_; $sub->($self); $self; }; sub DESTROY {};

      Which gives you:

      # call the whatever method and return $wrapped $wrapped->whatever # call the whatever method and return any value(s) $wrapped->raw_whatever # call the underlying method and wrap return value $wrapped->wrap_whatever # run $wrapped->$coderef and return $wrapped $wrapped->chain($coderef)

      So your second example would become something like (untested):

      my $file_dialog = Gtk::FileSelection ->Class::Chain::new("File Selection Demo") ->chain(sub {shift->wrap_ok_button ->label("Load") ->relief("half") ->width(80) ->height(50) ->signal_connect(clicked => sub { print $file_dialog->get_filename()->ret_val, "\n"; }); }) ->chain(sub {shift->wrap_cancel_button ->label("Exit") ->relief("half") ->width(80) ->height(50) ->signal_connect(clicked => sub{Gtk->main_quit}); }) ->set_filename("penguin.png") ->signal_connect(destroy => sub{Gtk->main_quit}) ->show();

      I still think it's ugly tho :-) :-)