Siaris
Simple Things
Syndicate: full/short
Siaris
Categories
General0
News2
Programming2
LanguageBits0
Perl50
Ruby10
VersionControl1
Misc1
Article Calendar
<= May, 2008
S M T W T F S
123
45678910
11121314151617
18192021222324
25262728293031
Search this blog

Key links
External Blogs
Brought to you by ...
Ruby
1and1.com

Subroutine References as Closures

Andrew L. Johnson (First published by ItWorld.com 2001-08-30)

A closure is a tricky kind of thing to explain, but not terribly hard to understand. The following may not meet with computer science approval as an explanation of closures, but the examples should provide enough hands-on exposure to grasp underlying concept.

The first thing we need to understand is that named subroutines are global by nature — that is, the subroutine name (identifier) lives in the package’s symbol table. However, they run within the lexical scope they were defined within:

    #!/usr/bin/perl -w
    use strict;

    {
        my $inc = 10;
        sub incr {
            print "$inc\n";
            $inc++;
        }
    }

    incr();
    incr();
    __END__

    prints:
        10
        11

In the above, $inc is lexically scoped within the block, and the subroutine (incr()) is defined within the same block. We can not refer to $inc after the block (scope) is finished, but we can call the subroutine and it runs in the scope it was defined in so it can still access $inc and change it.

A closure is simply an anonymous subroutine that is bound to the lexical scope it was defined within (rather like the above situation.

    #!/usr/bin/perl -w
    use strict;

    sub make_incr {
        my $inc = shift;
        return sub {print "$inc\n"; $inc++};
    }

    my $c1 = make_incr(10);
    my $c2 = make_incr(20);

    $c1->();
    $c2->();
    $c1->();
    $c2->();
    __END__
    prints:
        10
        20
        11
        21

Our make_incr() routine is a closure generator — it takes an argument and creates a new lexical variable. It then returns an anonymous subroutine that uses this same variable. Each time we call this routine a new lexical $inc is created and the anonymous subroutine refers to that particular copy of $inc. Each closure generated ($c1 and $c2) have their own private copies of $inc to work with. Essentially, they each can save information about their current state (in this case, what number they are currently at).

Here is another simple example (adapted from my book) where the closure itself also takes an argument:

    sub exclaim {
        my $prefix = shift;
        return sub {print "$prefix $_[0]!\n"};
    }

    my $batman = exclaim('Indeed');
    my $robin  = exclaim('Holy');

    $robin->('Mackerel');   # prints: Holy Mackerel!
    $batman->('Robin');     # prints: Indeed Robin!

Closures can be useful for creating callback routines and iterators. The above example of make_incr() creates very simple iterators that simply count up by ones from a given base number. However, you can create an iterator to iterate through more complex functions as well. Next week we will discuss using a closure as an iterator over the Fibonacci numbers.

*****