Simon Wistow (deflatermouse) wrote,
Simon Wistow
deflatermouse

You Get Me Closer To God

And ooooooooooooh, the music puns get worse and worse.

So, at work we stumbled across an interesting Perlism. Well, interesting if you're a huge nerd which, must as it pains me, I'm going to have to concede.

Anyway, so Perl has the concept of a DESTROY method which gets called on an object when it's, err, destroyed. Also, in Perl, objects can be any kind of a blessed scalar value - usually it's a hash reference but it could be a blessed array, or a bless sub routine reference. Which is where we join the story. Observe this:
my $foo = Foo->new;
$foo    = undef;

package Foo;

sub new {
    my $class = shift;
    return bless sub { print "Hello from Foo\n" }, $class; 
}
sub DESTROY {
    my $self = shift;
    $self->();
    print "Destroying Foo\n";
}
1;

We'd expect it to print
Hello from Foo
Destroying Foo

But it prints nothing.

How weird.

However if we do this (note the $class in the print statement):
my $foo = Foo->new;
$foo    = undef;

package Foo;

sub new {
    my $class = shift;
    return bless sub { print "Hello from $class\n" }, $class; 
}
sub DESTROY {
    my $self = shift;
    $self->();
    print "Destroying Foo\n";
}
1;

We get both statements printed.

Freaky, ne c'est pas?

So the reason, as far as I know is that DESTROY is only called when all references to the object are destroyed. Presumably for optimisation reasons, the anonymous subroutine in the first case is invariant and the new subroutine takes a reference to it and so the DESTROY is not called until the new goes away which it won't because the symbol table isn't wiped.

So the reason why the second one works is that by referencing the $class variable the anonymous sub is upgraded to a closure and a closure gets a new copy for every instantiation and thus gets DESTROYEDed.

It all makes sense if you squint at it askance but it's still the sort of thing that will trip you up.
Tags: hacking, perl, programming, weirdness
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 8 comments