[sf-perl] Book(s) for learning oo perl?

Chris Palmer chris at noncombatant.org
Mon Jun 12 12:13:43 PDT 2006


Speaking of books, Perl, and OOP, here is a message Mark Jason Dominus
just posted to the hop-discuss list.  hop-discuss is the discussion list
for his excellent book *Higher Order Perl*, which I gleefully and often
recommend, even to programmers who don't use Perl.

As for OOP itself, I have two additional suggestions: (a) don't
over-apply it; and (b) read up on its original applications, such as
multi-agent simulations (e.g. the language Simula, and the software
suite Swarm from the Santa Fe Institute).


==== Begin Forwarded Message ====

>From: Mark Jason Dominus <mjd at plover.com>
To: hop-discuss at plover.com
Date: Mon, 12 Jun 2006 14:56:38 -0400
Subject: Closures as destructors and cleanup objects

I was writing a class today that represents a flat-file database;
among the state inside the object are a filehandle and a record-number
counter.  The object supports a ->nextrec method that reads the next
record from the filehandle, and updates the current record number
inside the object.

I wanted to support certain methods that would need to save the
current position of the filehandle and the current record umber, seek
around in the file, and then put the object back the way it was, like
this:

        # save position
        my $pos = tell $self->{fh};
        my $recno = $self->{record_number};

        # do stuff that might mess up the filehandle
        ...

        # restore position
        seek $self->{fh}, 0, $pos;
        $self->{record_number} = $recno;

But of course the save-and-restore should be a method:

        my $position = $self->save_position;

        # do stuff that might mess up the filehandle
        ...

        $self->restore_position($position);

We can get a simpler interface by saying that the $position object
will restore the position itself when it goes out of scope:

        {
            my $position = $self->save_position;

            # do stuff that might mess up the filehandle
            ...
        } # position rewstored automatically

The way we normally do this in Perl is to have $position be an object
whose DESTROY method performs the restoration.

My first cut at this looked like this:

        sub save_position {
          my $self = shift;
          PositionSaver->new($self->{fh}, \($self->{record_number}));
        }

        package PositionSaver;

        sub new {
          my ($class, $fh, $recno_ref) = @_;
          my $self = [$fh, tell $fh, $recno_ref, $$recno_ref];
          bless $self => $class;
        }

        sub DESTROY {
          my $self = shift;
          my ($fh, $fh_pos, $recno_ref, $recno) = @$self;
          seek $fh, 0, $fh_pos;
          $$recno_ref = $recno;
        }

But instead, I decided to make the PositionSaver object a closure, one
which subroutine that performs the appropriate cleanup actions when it
is invoked.  Its DESTROY method just invokes it:


        package PositionSaver;

        sub new {
          my ($class, $fh, $recno_ref) = @_;
          my $fh_pos = tell $fh;
          my $recno = $$recno_ref;
          my $self = sub {
            seek $fh, 0, $fh_pos;
            $$recno_ref = $recno;
          };
          bless $self => $class;
        }

        sub DESTROY {
          my $self = shift;
          $self->();
        }


I thought this was simpler, but now that I see them side by side, I'm
not sure why I thought so.  I do like that the creation of the object
and the destruction instructions are all in one place.  

I've also seen this technique used in Damian Conway's Hook::LexWrap
module.  It seems simple and general, but I'm not sure it's really
worth doing.  Any thoughts about possible benefits or drawbacks that
I've missed?

==== End Forwarded Message ====


-- 
http://www.noncombatant.org/
http://www.boshuda.com/



More information about the SanFrancisco-pm mailing list