What are Closures?

Billy Joe Ramos
4 min readJan 13, 2022

How to easily understand this crucial concept for software development

Cat in a box looking curious with a tilted head
Can closures be compared to this cat?

Introduction

It is true that, in software development, you can do most things without even hearing about more complex concepts. It is also true that maybe you don’t need to learn how things work under the covers to construct a SPA frontend consuming a basic API in a local web server.

However, the path to becoming an insanely great (parodying Apple here) professional, including the problems that show up in the company you work, requires more basal knowledge, like strong OOP concepts, data structure, algorithms, design patterns etc. One concept that might help you grow as a developer (that you always use, but with little awareness) is the usage of Closures.

Preparing the land

There are some basic concepts required to understand Closures properly. These are:

  • Scope
  • Lexical scope

Scope and Lexical Scope

Acording to MDN Web Docs¹, in computer science, scope can be understood as the current context of execution, in which values and expressions can be referenced (by memory, when code is interpreted, organized, optimizing, and then transmited to machine instructions), with the most recognised being the global scope and local scope.

In the above example, x is in the global scope, while every y inside foo() and bar() are in the local scope. The variables in one function don’t affect others, despite having the same name, because one can not access the content (scope) of another. Or… do they?

Boromir Meme saying “One Does Not Simply Walk Into Mordor”
“One does not simply access the local scope of another”

That is what lexical scope is about; When a language offers supports lexical scope, a context can be easily nested and work just fine. Why is that? Because lexical scope considers the context (where) from the block of code!

Because a function is completely aware of its scope, you can define variables and functions inside functions, use it from outside, and keep going on. Take for example the above code: define_appearence() is inside draw_animal(), so it can be acessed from inside but not from outside; the same is valid for define_animal_type() inside define_appearence().

Pretty simple, right? You can almost treat it like a Matryoshka Doll!

Blue matryoshka doll organised in an asceding line
Nested scopes are easy with lexical scope

And what about the Closures?

Closure itself means “something that closes”, “means of enclosing” or “an act of closing”, according to Merriam-Webster dictionary². In computer science we can define it as the combination of an enclosed function with references to its surrounding state, giving you access to outer functions’s scope³. Still sounds complicated? Let’s look at an example.

In the example above, you’ll see how a closure can help define an internal behaviour, remebering the outer scope variable “tuned” to verify if Sinatra sings tuned or no, without the developer having to worry whatever goes before or after the sing() function (that is, in the end, what he’s receiving).

You have a closure whenever⁴:

  1. You have a nested function and
  2. The inner function (nested) refers to a value defined in the enclosing function (outter) and
  3. The enclosing function returns the inner function

You can use them whenever it is necessary to preserve context, remember values from functions even after execution (and the memory “cleans” that processing), avoid unnecessary use of global / nonlocal scopes (nonlocal keyword most specific for Python) or the uses that I’ll explain in the next topic.

Why can’t I just use classes then?

Well… you can. Most structural problems can be solved with a well structured OOP language like Java, his uglier sibling C# (just a joke .NET devs, just a joke) or even PHP, but sometimes you are using something more flexible, like JS and Python, without explicit typing or access modifiers in classes! Using closures is good way of keeping things private when constructing object-like data, with its attributes and behaviours; there’s even a name for that: Factory Functions (if you are more experienced in JS may have heard about that expression).

Besides that, if you only have one method besides the constructor, few implementations and a simple structure, why would you use a class? In those cases, the KISS principle (“Keep It Simple, Stupid”) may help us understand why this is not necessary.

Conclusion

This structure is widely used among libraries, packages, and modules, but usually we don’t notice, giving its simplicity and applicability. A great developer, engineer and related job positions that deal with software must know how to work and recognise situations where a closure would be the perfect fit for the job.

Basic concepts such as memory, functions, variables, and scope are crucial to be well understood, so that nested code won’t cause irregular recursion, infinite loops, memory leaks, bad performance, bugs and other problems that look like pure logic for the wise elders in programming, but reveals a lack of knowledge by those who write the code.

In the lifelong-learning journey that is dealing with programs, writing code and getting it to work is as easy as playing “Twinkle-Twinkle Little Star” in a Piano. But a Bach-level code can only be reached through reasearch, failing, experimenting, learning, and working on your flaws.

--

--

Billy Joe Ramos

Christian, Software Development and Engineering student with main projects focused in web platforms, also passionate about literature and music.