in reply to Building an anonymous subroutine

Sometimes a closure is an object waiting to happen. (And sometimes the reverse.) Consider:

package Encoder; ## Basic constructor sub new { my $type = shift; my $self = {}; bless $self, $type; } ## Define the common interface sub shared_stuff { return reverse $_[1]; } ## Define the uncommon interface sub other_stuff { die "Somebody didn't define the other stuff!"; } ## Generalized encoding method sub encode { my $self = shift; my ($text) = @_; $self->common_stuff($text); $self->other_stuff($text); }
That defines your base class, where all the common code can live.

Then, for each kind of encoder, you can define a subclass. For many subclasses, they'll be doing the same overall thing with variations, and you can just redefine the 'other_stuff' method. Otherwise, you can redefine 'encode' itself... but you'll still have 'common_stuff' to call if you want it.

# In Encoder/ package Encoder::B; use base 'Encoder'; sub other_stuff { my ($text) = @_; my $new_text = $text; $new_text =~ s/a/c/g; }

Then, finally, you only need a factory subroutine to create the right type of encoder for each user preference:

use Encoder::B; use Encoder::Whatever; our %Encoder_Table => ( 'b' => 'Encoder::B', 'c' => 'Encoder::Whatever', ); sub encoder_factory { my ($e) = @_; exists $Encoder_Table{$e} or die "'$e' is not a valid type of encoder, sorry!"; return $Encoder_Table{$e}->new(); }

And, finally, to get your new encoder and use it:

my $encoder = encoder_factory($whatever_e_is); print $encoder->encode("Hahahaha!");
There will be a speed hit, but it'll be faster than doing constant per-word checks, and easier to keep organized than closures-upon-closures-upon-closures.

Note: Code is untested and I've been drinking Cabernet.


Replies are listed 'Best First'.
Re: Re: Building an anonymous subroutine
by Anonymous Monk on Aug 13, 2002 at 12:39 UTC
    Closures upon closures is not intrinsically easier or harder to keep organized than subclasses upon subclasses.

    They just organize naturally in different ways. If a clean OO model fits your problem, then OO naturally channels you. If it doesn't, then using closures is better than trying to fight OO into an imitation of what you would do more naturally with closures. Particularly so in Perl where writing any OO involves so much infrastructure.

    BTW your extra method-call hooks could be replaced with a single method that is intended to be called from subclasses with SUPER. Less code and infrastructure, same result.