Skip to content
Swizec Teller - a geek with a hatswizec.com

JavaScript's native map reduce and filter are wrong

Last week I saw a tweet by @jhartikainen that made my heart skip a beat! He totally raped the definition of a one liner and made something that can be beautiful only to a giant functional programming nerd.

The gist that he posted looks like this:

//Is this abuse of array functions? :D
"20000001"
.split("")
.reverse()
.join("")
.match(/\d{3}|\d+$/g)
.map(function (s) {
return s.split("").reverse().join("");
})
.reverse()
.join(" ");
//produces "20 000 001"

Now this might just look like so much brain sputtering madness to you, but it's actually displaying something very awesome about one of my favourite programming languages -- native implementations of map, reduce and so on.

IMG_2307

tl;dr --> JavaScript is starting to mix functional and objective programming in a bad bad way

I'm not exactly certain when JavaScript got native implementations of these as I've been using libraries like underscore.js for a while now to achieve this exact same thing. Actually wikipedia tells me this has been added in version 1.6 way back in November 2005. Six years ago and I didn't know a thing about it.

That's just sad. Why don't more tutorials online talk about these features? How are people supposed to learn how awesome JavaScript is when most of the community works only with a very small subset of the language?

Some further searching tells me that the version of JavaScript most browsers currently support is 1.5 and since ECMAScript version 5, which is comparable to JavaScript 1.8, was only standardised in ... December 2009, the browsers are quickly trying to pick up slack and get up to speed with that ...

This makes me sad, I almost don't feel like continuing this post ... luckily though, Node.js is pretty good with the latest ECMAScript support so there's still hope.

What's wrong

Considering the horror show I just described, writing the rest of this post leaves a bad taste in my mouth, but I think the way JavaScript natively implements some features of functional programming is wrong.

The way map, reduce, filter and others are implemented in JavaScript is that they are methods of the Array class. And you call them as such:

[0, 1, 2].map(function (i) {
return i + 1;
}); // adds 1 to every member
[0, 1, 2].reduce(function (a, b) {
return a + b;
}); // sums members
[0, 1, 2].filter(function (i) {
return i > 0;
}); // removes members smaller than 1

As you can see all of these functions are a way to call a certain function on every member of the array. Nothing too special here, anyone who's ever even sniffed at functional programming should understand how these three functions work.

But because JavaScript is a language that is both functional and objective in its design, this code suddenly becomes very ambiguous to read.

On one hand, you're calling functions that are the epitome of functional programming. Obviously there are no side-effects and a copy of the array is returned, leaving the original intact. Immutable data structures and all that functional shebang.

But on the other hand, you're calling these on an array, as the array's methods. Obviously these functions belong to the Array and are therefore executed in place and the array's state is changed.

Reading the syntax and knowing the basics of both objective and functional programming, both those opinions look like they should be true. Shouldn't they?

Turns out, in this case, JavaScript returns a copy of the array and nothing at all happens to the original array. As we can demonstrate with the following quick test in the node.js console:

Merrick:~ Swizec$ node
> var a = [1,2,3];
> var b = a.map(function (i) { return i+1; });
> a
[ 1, 2, 3 ]
> b
[ 2, 3, 4 ]
> a.map(function (i) { return i+1; });
[ 2, 3, 4 ]
> a
[ 1, 2, 3 ]

So it would seem that what we have here is a case of functional programming, behaving as functional programming, neatly packaged into an objective syntax.

Which I guess wouldn't actually be that bad were it consistent.

Other functions used in this exact same way usually change the array's state. Both sort and reverse return the new array ... but also change the original array's ordering. Similarly every other function on the array ranging from shift and pop to _splice _change the state of the array they are being called on and return ... something (it depends on the particular function).

This means that reading JavaScript you are faced with the fact that functions called on objects are sometimes performing actions on the copy of the object and sometimes on the object.

That's just confusing and bloody horrible from a language design standpoint don't you think?

Why couldn't they just create new global functions for these awesome functional programming concepts ... I mean, the whole idea there is that functions get parameters and only parameters, functions in functional languages are supposed to be context independent. But here you have context dependent functional functions ... it's just a mess.

Is JavaScript fast becoming like PHP with its confused standard library? Or is it just going through a little identity crysis?

Enhanced by Zemanta

Did you enjoy this article?

Published on June 29th, 2011 in Uncategorized

Learned something new?
Want to become a high value JavaScript expert?

Here's how it works 👇

Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet 📖right away. After that you'll get thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over my 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

Start with an interactive cheatsheet 📖

Then get thoughtful letters 💌 on mindsets, tactics, and technical skills for your career.

"Man, love your simple writing! Yours is the only email I open from marketers and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"

~ Ashish Kumar

Join over 10,000 engineers just like you already improving their careers with my letters, workshops, courses, and talks. ✌️

Have a burning question that you think I can answer? I don't have all of the answers, but I have some! Hit me up on twitter or book a 30min ama for in-depth help.

Ready to Stop copy pasting D3 examples and create data visualizations of your own?  Learn how to build scalable dataviz components your whole team can understand with React for Data Visualization

Curious about Serverless and the modern backend? Check out Serverless Handbook, modern backend for the frontend engineer.

Ready to learn how it all fits together and build a modern webapp from scratch? Learn how to launch a webapp and make your first 💰 on the side with ServerlessReact.Dev

Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️