Saturday, March 10, 2012

Caveat Scriptor: Closures

Closures are a flexible and powerful concept.  However, you have to keep in mind certain caveats when writing them.

Understand how the closure will grow
  • You can easily create a memory leak with a closure because the only interface to the allocated memory is through the closure (typically). You should make sure your closure will not grow unbounded.
Watch out for capturing references
  • This is more of standard gotcha, but it's even more important when dealing with closures. A closure will capture lexical variables including ones that contain references. This means whatever those references point to will continue stick around as long as the closure is around, unless they are explicitly weak refs.
Don't close over variables you don't need to close over
  • It's wasteful, bad code and makes it more likely you'll introduce a memory leak.
Make the functions that will become closures as simple as possible
  • The bigger, more complex the function that will become a closure, the more likely you are to have a bug which may lead to a memory leak.
Don't create closures when they aren't needed
  • See: common sense
§

Wednesday, March 7, 2012

An Abrupt Introduction: Closures

A closure is created by a first class function creafing and returning a function which captures the lexical bindings of the free variables in its defining environment. Once it has captured the lexical bindings the function becomes a closure because it "closes over" those variables.

Note this means closures only exist at run time.  However, it has become common to refer to the function that will become a closure as a closure.

In practical terms a closure is a function that has data attached to it.  The data retains it's state across calls.  Here is a trivial example of a closure in python:

def return_a_closure():
    total = [0]
    def adder(num=1):
        total[0] = total[0] + num
        return total[0]
    return adder

closure = return_a_closure()
closure() # returns 1
closure() # returns 2
closure() # returns 3

When creating a closure you are not limited to binding only one function or only one piece of data.  You can even share data between multiple closures.

def return_a_closure():
    total = [0]
    def adder(num=1):
        total[0] = total[0] + num
        return total[0]

    def deducter(num=1):
        total[0] = total[0] - num
        return total[0]

    return adder, deducter

add, deduct = return_a_closure()
add()    # returns 1
add()    # returns 2
deduct() # returns 1
add()    # returns 2
deduct() # returns 1

§

Friday, March 2, 2012

Configuring SSH: Creating a Command Key

OpenSSH provides the capability of binding a particular key to a command.  This is often the best way to execute a remote command without the risk of sending a password over the network.

  1. Change directory to your .ssh directory. (ie. cd ~/.ssh)
  2. Create the key pair. (ie. ssh-keygen -N "" -f hello_world)
  3. Add the key to the authorized_keys file along with the command. (ie. echo -n 'command="echo Hello World"' | cat - hello_world.pub >> authorized_keys)
  4. Try it out! (ie. SSH_AUTH_SOCK=/dev/null ssh -o BatchMode=true -qi hello_world localhost)
§