Gist of the Day: Perl Closure Extravaganza!

Hey all, so I’ve been asked to do something a little more in-depth, and I’ve been given no requests, so I picked closures in Perl.

About Closures

A closure is a function which was created dynamically inside of another function. In Perl (among other languages), these are sometimes referred to as anonymous subroutines. In Perl, all closures are anonymous subroutines, but not all anonymous subroutines are closures. The key differentiating feature is scope: a closure has access to lexically-scoped variables within a containing subroutine, whereas an anonymous subroutine is not necessarily even inside of a function.

Closures Versus Anonymous Subroutines

Here is an example of  an anonymous subroutine:

Notice how this creates a CODEREF and then executes it. This is essentially just a normal function. To contrast, here is an example of a closure:

Notice how this is a function which returns a CODEREF, and then when you call that CODEREF it has access to the @inputs variable of its containing function.

Why Use Closures?

This of course brings up the question of why you would want to use closures. There are three very common instances where closures are a very good solution:

  1. When you are doing asynchronous tasks, such as loading data or processing large amounts of data
  2. When you need to use custom functions to process data (think sorting compare routines)
  3. When you want to create or consume a library or application where one application’s code interacts directly within the other’s.

Nuts & Bolts

The biggest confusion I had when I was first exposed to closures – way back when – was when does the memory in a variable (like @inputs above) get reaped by the garbage collector? Well, those variables get reaped whenever anything referencing them gets reaped. That means that after line 8 when we undef $closure; is when that @inputs gets reaped.
Prove it, you say? Okay, but first we have to have a way of detecting when a variable is reaped. With OO Perl this is easy, just handle the DESTROY() method. Here’s a quick example of that type of code:

Now that we have this piece of code we can prove this. Here’s a snippet using the above DestroyDetector class to demonstrate how the garbage collector:

First we prove that an undef() call will trigger the DESTROY() function which prints the message. Then we create a function which returns a closure, which we then exercise. Finally, we undef the variable holding a reference to the closure and we observe the message announcing the destruction of the closure.
Here’s the output:

Announcing DestroyDetector "about to undef foo1" value: foo1
Destroying DestroyDetector value: foo1
Announcing DestroyDetector "Pre-closure definition..." value: closure1
Announcing DestroyDetector "calling from the closure!" value: closure1
Announcing DestroyDetector "About to undef() the closure..." value: closure1
Destroying DestroyDetector value: closure1
You should have just seen the DestroyDetector destroy "closure1".

The Full Gist

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.