When you’ve spent years coding pretty much everything in Java, it’s hard to break out of the Java way of doing things. It means that you tend to forget that other languages might have things called closures, for example. Here’s how a closure looks in Python:
lambda x:dosomethingto(x,anothervariable)
The neat thing is that this closure can be passed around like a first class object. Also, anothervariable
, bound in the outer scope, is accessible to the lambda expression when it is invoked later. You can do stuff like:
if isinstance(somevalue, int) or isinstance(somevalue, float):
isfunny=lambda x:log(x)>somevalue
else:
isfunny=lambda x:isalpha(x) and islower(x)
funnyitems=[item for item in mylist if isfunny(item)]
seriousitems=[item for item in mylist if not isfunny(item)]
Sure there are other ways to do the same thing. But this is arguably more elegant.
There’s also nested functions, which are kind of like closures. Rather than contriving an example, I’ll give one from the book I’m reading, Programming Collective Intelligence. In chapter 8, a crossvalidation function is defined. Forgetting the specifics and purpose of this function, just know that the crossvalidate
function returns low numbers for good solutions and high numbers for bad solutions. Earlier in the book, we’d already been introduced to optimisation problems and cost functions. The cost functions take a single argument, which is a potential solution to be costed. The crossvalidate function takes a bunch of parameters, so for this and other reasons it can’t be used directly. But you can do something like this:
def createcostfunction(algf, data):
def costf(scale):
sdata=rescale(data,scale)
return crossvalidate(algf,sdata,trials=10)
return costf
So now your costf
function knows about algf
and data
, despite not having them as parameters. That is, the bound variables to algf
and data
are available to costf
when it is called at some later time:
costf=createcostfunction(knearest,mydata)
annealingoptimise(wdomain,costf,step=2)
So when annealingoptimise
eventually invokes costf
, costf
has access to knearest
and data
. That is the bindings of algf
to knearest
and data
to mydata
live on after the execution of createcostfunction
completes. Cool.
1 reply on “Rediscovering closures and nested functions”
[…] 2008ricky It’s probably time to come clean about my recent spate of posts on startups, Ruby, Python and so on. Well, there are a few things about peer review and publishing in the realm of academia […]