Back to Basics: Anonymous Functions and Closures

Anonymous functions and closures are a useful concepts included in most modern programming languages. Like so many elements of modern programming, the closure has its origins in the early Lisps.

Anonymous functions are used heavily in JavaScript for many things, most notably the many callbacks used by the language’s many frameworks. In Ruby we see them most often in their block format.

First let’s look at anonymous functions. An anonymous function allows a developer to create a function that has no name. In other words anonymous functions can be used to store a bit of functionality in a variable and pass that piece of functionality around. First let’s look at an example using an anonymous function in Ruby and JavaScript:

[1, 2, 3].map do |number_to_double|
  number_to_double * 2
end
_.map([1, 2, 3], function(numberToDouble) {
  return numberToDouble * 2
})

Above we use the Ruby Array‘s map method and the JavaScript library Lo-Dash’s map method. In both cases we provide a callback. The Ruby example uses a block and the JavaScript example uses a function. These callbacks are anonymous functions. We specify a bit of functionality, in this case multiplying the number provided by two, and then pass that functionality to the map method. In our example the resulting array would be [2, 4, 6]. Because we’re allowed to define the functionality we want to use to modify the elements of our array it makes it much easier to create reusable code. As opposed to creating many different map methods, each that modified the contents of the array in a different way, we only need one that allows us to provide it with the functionality our specific use case requires.

Closures have to do with the connection between functionality and the variables that are available to said functionality when it’s executed. When a closure is created it can reference any of the variables available in its lexical scope and as a result is said to close over its environment. This raises the question, what is a lexical scope? Lexical scoping simply means that variables refer to their local environment.

Let’s look at an example to help clarify:

Ruby lexical scoping

def lexical_scope_example(multiplier)
  [1, 2, 3].map do |number|
    new_number_to_double = number * multiplier
    new_number_to_double * 2
  end
end
ruby > lexical_scope_example(5)

[10, 20, 30]

In our Ruby example we have two lexical scopes:

  • The lexical_scope_example function has the parameter multiplier
  • The block we pass to the map method can access the multiplier, number and new_number_to_double variables

JavaScript lexical scoping

function lexicalScopeExample(multiplier) {
  return _.map([1, 2, 3], function(number) {
    var newNumberToDouble = number * multiplier
    return newNumberToDouble * 2
  });
}
javascript > lexicalScopeExample(5)

[10, 20, 30]

In our JavaScript example we have two lexical scopes:

  • The lexicalScopeExample function has the parameter multiplier
  • The block we pass to the map method can access the multiplier, number and newNumberToDouble variables

It’s interesting to note that the block’s lexical scope includes the variables which belong to the lexical scope it is created in. The inverse is not true. Variables defined in the block’s lexical scope are not then available to the function’s lexical scope. Let’s take a look at what happens if we try to access the new_number_to_double variable outside of the block’s lexical scope. In this case our anonymous function has closed over its environment.

Ruby variable outside of block’s scope

def lexical_scope_example(multiplier)
  [1, 2, 3].map do |number|
    new_number_to_double = number * multiplier
    new_number_to_double * 2
  end

  puts new_number_to_double
end
ruby > lexical_scope_example(5)

NameError: undefined local variable or method `new_number_to_double' for main:Object

JavaScript variable outside of block’s scope

function lexicalScopeExample(multiplier) {
  return _.map([1, 2, 3], function(number) {
    var newNumberToDouble = number * multiplier
    return newNumberToDouble * 2
  });

  console.log(newNumberToDouble)
}
javascript > lexicalScopeExample(5)

ReferenceError: newNumberToDouble is not defined

Now that we’ve taken a look at lexical scope let’s revisit how they pertain to closures. Closures allows us to define units of functionality while maintaining references to all the variables that exist in the lexical scope they are defined. These units of functionality can then be executed in a different lexical scope. Let’s take a look at an example.

Ruby in different lexical scope

def scope_two
  yield
end

def scope_one
  closure_addend = 3

  scope_two do
    closure_addend += 5
  end

  puts "The variable in our main lexical scope after the method is executed
    equals #{closure_addend}"
end
ruby > scope_one

The variable in our main lexical scope after the method is executed equals 8

In our Ruby example we have three lexical scopes:

  • The scope_one function includes the closure_addend variable
  • The block we define when we call the scope_two function includes the closure_addend variables

Let’s walk through the Ruby version step by step:

  • In irb we call our scope_one function
  • Within this function we create the closure_addend variable and assign it the value of 3
  • Within the lexical scope of our scope_one function we define a block and pass it to the scope_two function
  • Inside the new lexical scope of the scope_two function we execute our closure
  • Inside of our closure we add 5 to the closure_addend variable we defined within the lexical scope of the scope_one function
  • We then return to our scope_one lexical scope and puts our closure_addend variable, which has now been incremented by 5

JavaScript in different lexical scope

function scopeTwo(callback) {
  callback();
}

function scopeOne() {
  var closureAddend = 3;

  scopeTwo(function() {
    closureAddend = closureAddend + 5;
  });

  console.log("The variable in our main lexical scope after the method is
    executed " + closureAddend);
}
javascript > scopeOne()

The variable in our main lexical scope after the method is executed equals 8

In our JavaScript example we have three lexical scopes:

  • The scopeOne function includes the closureAddend variable
  • The function (closure) we pass when we call the scopeTwo function includes the closureAddend variables

Let’s walk through the JavaScript version step by step:

  • In the browser console we call our scopeOne function
  • Within this function we create the closureAddend variable and assign it the value of 3
  • Within the lexical scope of our scopeOne function we define a function and pass it to the scopeTwo function
  • Inside the new lexical scope of the scopeTwo function we execute our closure that we called callback
  • Inside of our closure we add 5 to the closureAddend variable we defined within the lexical scope of the scopeOne function
  • We then return to our scopeOne lexical scope and log our closureAddend variable, which has now been incremented by 5

The interesting part of this is that our closure gets executed in a completely different lexical scope than it was created in, but still has access to the variables in the original scope. It’s also important to notice that the modifications that occur in the new lexical scope affect original value, because it is the same value.

Let’s take a look at what would happen if we attempted to access the closure_addend variable in the scope_two function’s lexical scope.

Ruby variable in other method’s scope

def scope_two
  yield
  puts "We just modified this variable in the block above #{closure_addend}"
end

def scope_one
  closure_addend = 3

  scope_two do
    closure_addend += 5
  end

  puts "The variable in our main lexical scope after the method is executed #{closure_addend}"
end
ruby > scope_one

`scope_two': undefined local variable or method `closure_addend'
  for main:Object (NameError)

JavaScript variable in other method’s scope

function scopeTwo(callback) {
  callback();
  console.log("We just modified this variable in the block above " + closureAddend);
}

function scopeOne() {
  var closureAddend = 3;

  scopeTwo(function() {
    closureAddend = closureAddend + 5;
  });

  console.log("The variable in our main lexical scope after the method
    is executed " + closureAddend);
}
javascript > scopeOne()

ReferenceError: closureAddend is not defined

The ability to maintain references to the lexical scope at the time of definition is especially useful in callbacks. This is used extensively in JavaScript. It’s common to provide an asynchronous action with a callback to be executed upon completion. The lexical scope that this callback is executed in is often the framework’s we’re using.

What’s next

If you found this useful, you might also enjoy: