Paul Nathan
Paul Nathan

Reputation: 40319

Destructors without classes

Suppose I have a function that returns a closure:

sub generator
{

   my $resource = get_resource();
   my $do_thing = sub
   {
     $resource->do_something();
   }

  return $do_thing;
}

# new lexical scope
{
   my $make_something_happen = generator();

   &$make_something_happen();
}

I would like to be able to ensure that when $make_something_happen is removed from scope, I am able to call some $resource->cleanup();

Of course, if I had a class, I could do this with a destructor, but that seems a bit heavyweight for what I want to do. This isn't really an "object" in the sense of modelling an object, it's just a functiony thing that needs to execute some code on startup and immediately prior to death.

How would I do this in Perl( and, out of curiosity, does any language support this idea)?

Upvotes: 2

Views: 153

Answers (2)

Jim
Jim

Reputation: 19

I think I understand your question. In my case I want:
* A global variable that may be set at any point during the script's runtime
* To last right up to the end of the life of the script
* Explicitly clean it up.

It looks like I can do this by defining an END block; It will be run "as late as possible". You should be able to do your $resource->cleanup(); up in there.

More here: http://perldoc.perl.org/perlmod.html#BEGIN%2c-UNITCHECK%2c-CHECK%2c-INIT-and-END

The begincheck program on that page has the code.

Upvotes: -1

brian d foy
brian d foy

Reputation: 132896

I'd just use a class for this. Bless the subroutine reference and still use it like you are. The get_resource then uses this class. Since I don't know what that looks like, I'll leave it up to you to integrate it:

 package Gozer {
      sub new {
         my( $class, $subref );
         bless $subref, $class;
         }

      sub DESTROY {
         ...; #cleanup
         }
      }

If every thing can have it's own cleanup, I'd use the class to group two code refs:

 package Gozer {
      sub new {
         my( $class, $subref, $cleanup );
         bless { run => $subref, cleanup => $cleanup }, $class;
         }

      sub DESTROY {
         $_[0]{cleanup}();
         }
      }

In Perl, I don't think this is heavyweight. The object system simply attaches labels to references. Not every object needs to model something, so this is a perfectly fine sort of object.

It would be nice to have some sort of finalizers on ordinary variables, but I think those would end up being the same thing, topologically. You could do it with Perl as a tie, but that's just an object again.

Upvotes: 5

Related Questions