Bringing the querying power of SQL to JavaScript
Hello and Happy New Year to everyone, I have been really busy recently and it has been long time I didn't write, however do not worry I didn’t forget I have to finish my functional programming series of articles.
This post comes directly from a session I presented internally about JavaScript advanced programming concepts. I thought it would be a good idea to share some of its content on this blog. This session was mainly to show how to take advantage of the prototype and functional paradigms that JavaScript supports.
If you read my previous articles about F#, you probably understood how useful functional programming concepts are, when it is about handling sets of data. JavaScript does not have the linked list based on pairs representation that most functional programming have, however it has arrays. Let see how we can easily increase the power of JavaScript by extending its Array type with an SQL like query mechanism based on the most functional programming common functions.
First a word about JavaScript arrays…
JavaScript arrays are associative arrays, also called map or dictionaries in other languages. It means they associate a key to a value. Because JavaScript is dynamically typed you can use arrays with mixed keys, or values types.
As you probably know, almost everything in JavaScript is object. However what you perhaps ignore is that all objects are arrays, I don't mean they are based on the Array JavaScript type nor that they share its prototype, but they behave as arrays. Indeed objects slots may be represented as an associative array of properties, since function are closure in JavaScript (aka. first class values) they can be used as values for properties thus representing the concept of methods. So improving the way we use array is not only good to work on data, but also good to work on the code, for meta-programming.
The code below shows that objects and surprisingly even functions (which are objects) can be used as arrays:
JavaScript function doesn’t really have a fixed parameter prototype, thus function arguments number may vary, so it is important to know they can be obtained through the arguments special object variable (not of type Array):
You can see in the example above that it is possible to use Array methods through the Array prototype on non Array type objects because they behave the same.
About the curry function:
Wikipedia:
In mathematics and computer science, currying is the technique of transforming a function that takes multiple arguments (or a tuple of arguments) in such a way that it can be called as a chain of functions, each with a single argument (partial application). It was originated by Moses Schönfinkel and later re-discovered by Haskell Curry. Because of this, some say it would be more correct to name it schönfinkeling.
So from a practical point of view curry helps us to create partially applied functions on the fly without typing a lot of code.
Fold, map, filter the essential tools
In this section I assume you know what the notion of catamorphism is and what are the fold, map and filter functions, if you don’t please read my previous article 1st Class Functions – Power is in simplicity.
Fold can be defined recursively, but since JavaScript works with array and for performance reasons as it should be considered as a collection processing function building block, I prefer to implement it with a loop. It is interesting to highlight that optimizing terminal recursions is not a part of the JavaScript standard but that the most used script engines optimize it.
Here an implementation of fold left in JavaScript:
Once we have fold, we can define map and filter in terms of it:
We can now do funny things with arrays of data:
Give me some power
Now that we have the map and filter operations, let’s augment and empower the JavaScript Array prototype.
We can now use the select and where methods on any new Array type instances.
Look how easily we can query data!
As shown you can use the built in sort operation, and if you need a join don’t forget the concat method. Since from the past few years applications started to become more and more client based, those short functional helpers defined by less than 10 lines of code appeared to me to be quite useful when processing data incoming from web services. As a comics guy would say “With great power comes great responsibility”. I hope you will have great use of it.