My day job involves programming in Go. One feature I like about Go is "defer". Any function that's deferred gets ran at the end of the functions scope. As a very simple example, the program below prints

hello world

instead of the other way around, because "world" is deferred until the main() function exits.

package main import "fmt" func main() { defer fmt.Println("world") fmt.Println("hello") }

I find this cleaner: you can write clean-up closer to where you allocate/acquire resources, instead of remembering to do it at the end of your function. In order to do this in perl, I created a defer() function which, given a subref, returns a wrapper subref blessed into a dummy package. Then, I give that dummy package a destructor (DESTROY) which calls itself. The result is that the subroutine given will be run when the variable it is assigned to goes out of scope:

use v5.10.1; use strict; use warnings FATAL => "all"; sub defer{ my ($sub) = @_; my $pid = $$; return bless sub { # I check that I'm running in the process that I called defer() in, # because I don't want child processes to call $sub->(); if ($$ == $pid) { $sub->(); } }, 'my_deferer_dummy_package'; } sub my_deferer_dummy_package::DESTROY { my ($self) = @_; $self->(); }

To give a simple usage example, we create a function which opens a file and defers it's close()ing:

sub upper_caser { my $file = shift; open my $fh, '<:crlf', $file; my $defered = defer sub { say "defer function called!"; close $fh; }; while (defined(my $line = <$fh>)){ chomp $line; say uc $line; } }

there's a file called "test.txt" containing the lines:

just another perl hacker

Now, calling the function,

upper_caser "test.txt";

it yields:

# JUST # ANOTHER # PERL # HACKER # defer function called!

I also found this very useful in functional programming, when I want to return an iterator subroutine, but also clean-up after it when it is no longer needed:

sub make_upper_caser_iterator { my $file = shift; open my $fh, '<:crlf', $file; my $defered = defer sub { say "defer function in closure called!"; close $fh; }; return sub{ # make sure that the closure captures $defered # and keeps it alive as long as this closure is. my $defered = $defered; if (defined(my $line = <$fh>)){ chomp $line; return $line; } return; }; } my $iter = make_upper_caser_iterator "test.txt"; while (defined(my $line = $iter->())){ say uc $line; }

As expected, the above use of the iterator yields: