vendredi 15 février 2013

Closures from JS to Golang

Introduction

    You remember that weird feeling you had the last time you wrote non-trivial amounts on Javascript? Some sort of constant "this shouldn't be happening impression". Well JavaScript, or more specially ECMAScript the standard on which it is based, follows rules that may seem at times counter-intuitive. However some of those design decisions are the reason why JavaScript is so broadly accessible and generally accepted.

    In this entry, we will be discussing about one of the main aspect you are confronted with when writing code in ECMAScript, Closures. It is important to note though that closures are can not only be found in this language but in a variety of others : C#, Python and Golang to name just a few.

Quick examples


I will try to give an example of the same Closure in JavaScript, C#, Python and Golang. Bonus points for those who already did some functional programming, this is a basic example of currying.

What they are not.


Now that we have a gut feeling about what is a closures we can get in the real stuff. It is important to understand that closures are not our basic function pointers. They are much much more.

What are closures?


Closures are a way to bind a lexical context with a piece of code.

Lexical Context


The lexical context is the sum of every handle and variables that was available when the closure was created. It's its environment at the moment of creation, in other word.

A Wild Functor Appears


Remember writing functors? For most of you, this must seem like a ghost from Christmas past. If we put them in context with what we just saw, functors are a lot like closures. They provide some sort of context that is bound to a function "operator()". We can even rewrite the same sample we used earlier.


Cool eh? I bet you always wanted to know how to emulate JavaScript in C++ [sic].

What is so special about JavaScript then?


In JavaScript every function is a closure. Not only that, functions in JavaScript not only get the lexical context of when they were created but also the execution environment of the callee.


Another thing to remember is that, the this keyword is exactly that, a keyword. It returns the object in which the function you are will be inserted. ( In the case of most anonymous function in JavaScript this means the "window" object.)

As the standard says : 

The this keyword evaluates to the value of the ThisBinding of the current execution context.

Here is an example :


But why should I care about what JavaScript do?

Well, as we mentioned earlier, closures can be found in a variety of languages. If you are a programmer, there are very good chance that you already have written some even if it was unbeknownst to you. Understanding them is therefore essential.

You have been reading about them for some time now, it's time to get into applications. Let's look at another C# example.


You can notice that I have not written what it shown on the console for this one. It's for you to take a guess.

If your guess was all "5", then you are correct. In C#,  for-each  use reference for the iteration variable. Therefore the closure only gets a reference to the "i" variable and in each iteration of the for-each loop, the reference value gets modified.

It is for that reason that when we print them all, we get only "5", it effectively print 6 time the same reference.
If you want to do this sort of things you must use a local temp variable that you set to the loop iterator value and then pass the local variable to the closure.

Useful application of closure in JavaScript.


Not that we have a good feel about what closure are and how to use them. Let us look at a useful application of them in JS. Here is the situation :

A large candy company as launched a online contest to guess the number of bubble gum is produce each year. If you get it right, you win the equivalent of your weight in candy.

Here is a trivial, and broken implementation :

The console.log shows us why this is not exactly what the company wanted in term of difficulty... Now, lets try to do the same thing using closures.

This is more what we had in thought!
As you have probably understood now, this example was to show how to create private variables in a language that doesn't offer a way to do it by default.

Conclusion


In this blog entry, we have learn at what are closure and what is the difference between them and function pointers. We also saw that you can find closures in most modern languages. We have seen what makes there use so peculiar in ECMAScript dialects and at the same time how they can be harness to provide additional features and functionalities.

I hope that from now on, you will refrain from placing them in the "this provides undefined behaviour" and start noticing when they could be used to clear-up and enhance you codes.

This article will be followed by more on the topic of functional programming but I had to tackle closures before going further.

P.S. Do not hesitate to ask precisions, or to write suggestions in the comments.

Aucun commentaire:

Enregistrer un commentaire