At Fri, 24 May 2002 17:10:19 +1000, Mark Johnathan Greenaway wrote:
> > i mostly agree. the big thing holding me back from python is
> > closures. once python gets proper anonymous, lexically scoped
> > subroutines things will start to look up.
> Does
> from __future__ import nested_scopes
> do what you want? Sorry, I haven't read the definitions of lexical etc.
> scoping in some years now.
in perl (as in python, etc), you can create "anonymous functions" on
the fly. its *really* good for callbacks, and makes them a very nice
option when designing interfaces.
in C, every function pointer has to be accompanied by a void
*private_data, so you can pass "instance data" to the callback. in
C++, the same thing happens implicitly with methods and object data.
with closures, there's no need, since the "state" is already captured
inside the function when its defined.
this may seem like a contrived example, but its a situation that pops
up quite often once you start throwing callbacks around:
#! /usr/bin/perl -w
# yes, this is a complete, working perl-tk program
use Tk;
sub setup {
my $main = shift; # the first argument passed
my $counter = 0;
my $label = $main->Label(-text => 'Hello World')->pack;
$main->Button(-text => 'Quit',
-command => sub {
# exit if it's the second time we're called
$main->destroy if $counter++;
# change the label text
$label->configure(-text => 'Goodbye World');
})->pack;
}
my $top = new MainWindow;
setup($top);
MainLoop;
assuming you can recognise the constructs, it seems all very simple
and straightforward.
BUT: consider that by the time the Button callback is called, we're
inside MainLoop(). that means that setup() has exited and $counter,
$label or $main have fallen out of scope and no longer really exist on
a conventional "stack"(1). (a "nested scope" doesn't persist like
this (from what i understand of python))
the anonymous subroutine used for the callback remembers the
environment in effect when it was defined, and keeps a reference to
all of the "lexical" (basically non-global) variables used, so they
are still availble when the enclosing function is cleaned up. the
anonymous function and captured lexical variables combo is known as a
"closure".
remember that these variables are not global. they are unique to that
particular closure. consider (for example) what happens when you add
another "setup(new MainWindow);" below the other one. the second
callback gets an entirely new $counter, $main and $label which has
nothing to do with the earlier ones now stored away somewhere in the
first closure.
the fact that you just think: "well, yeah. thats the way its supposed
to work isn't it?" before you think about the implementation details
shows just how powerful closures really are.
(1) not that perl put them on a stack as such in the first place, but
i'm comparing against something like C here.
--
- Gus
--
SLUG - Sydney Linux User's Group - http://slug.org.au/
More Info: http://lists.slug.org.au/listinfo/slug