The functional language that’s right under your nose

Recently I’ve been getting an itch to learn a functional programming language. I’ve made a couple attempts on Lisp over the years, with mixed results; I can write fairly basic Common Lisp, and hack on Emacs a bit, but I’ve never advanced much beyond that. I’d been looking at some of the trendy, popular functional languages (well, popular among certain circles) like Haskell, OCaml and Erlang, when I remembered that I already knew a functional language. In fact, part of the reason why I was hired at my current job was to write in it. And, as I browsed through a discussion of functional languages on reddit, it was literally right under my nose.

Yup, I’m talking about JavaScript.

Digression: stupid things people say about languages

Programming languages tend to be a bit like religions: people get attached to them, develop unshakable faith in them and are all too willing to wish hellfire and damnation on heretics who won’t see the light. As a result, they tend to spew out misconceptions about other programming languages in much the same way that a Protestant fundamentalist goes around saying Catholics are idolaters.

For example, a lot of folks who aren’t card-carrying members of the Church of Python (blessed be Guido and all His works) like to go around saying that Python isn’t “really” an object-oriented programming language, because you have to use self.

Now, this argument really doesn’t make any sense; when defining a method on a class, the first parameter to it is self, and inside the method you reference attributes of the class instance you’re working with as self.this and self.that and so on and so forth. The reason behind this is simple: it explicitly establishes variable scope (think about it: take away the self, and you get things like foo = 3 — is that the attribute foo of the class instance, or is it a variable local to the method? Using self.foo = 3 for the former case and foo = 3 for the latter does away with the ambiguity). Plenty of other languages do this; for example, Java uses this and Ruby uses @. Nobody tries to argue that Java or Ruby aren’t “really” object-oriented because of that; Python goes a little further and requires you to explicitly list self as an argument to the method, but Python people like being explicit. If being explicit about scoping means Python isn’t really object-oriented, then being explicit about the types of variables and function return values means Java doesn’t really have a type system.

A lot of people will also say horrible things about JavaScript, because despite being a really interesting language, lots of people don’t like JavaScript (well, to be perfectly honest, lots of people don’t like the available implementations of JavaScript and, to be really honest, lots of people particularly don’t like the available implementations of one API that’s used a lot in JavaScript). For example, I’ve seen people try to argue that JavaScript isn’t “really” object-oriented because you don’t define classes using a class keyword. JavaScript uses prototype-based inheritance, rather than class-based inheritance, but it is still a thoroughly object-oriented language.

Anyway, the whole point of these examples is to show that lots of people say silly wrong things about programming languages all the time, and mostly it’s got more to do with some agenda they’re pushing than with anything remotely resembling reality.

One of the things people might tell you is that JavaScript isn’t a functional language. They’re right, but only for certain values of “functional”.

What makes functional programming?

If we want to be pedantic about it (and if you know me, you know I always want to be pedantic), there are a few things which characterize “pure” functional programming:

  • Obviously, everything is accomplished by calling functions. There are no “standalone” lines of code — the program starts by calling a function, which calls a function, and so on. Depending on what the program does, it may eventually terminate, or it may simply continue running indefinitely. In any case, everything takes place inside a function body.
  • There is no global state and, to be perfectly pure, there are no global variables. Values can be passed into functions, but those values come from other functions, either as return values or as arguments passed from one function to another. But there is no “global scope”; each function has only a local scope to work with (even closures; their scope is just a bit wider and more long-lived than everybody else’s).
  • There are no “side effects”. This is a consequence of the lack of global scope or state; since a function can’t “see” much, if anything, beyond its local scope (again, closures are a weird case), there is no way for a function to modify anything that isn’t handed to it.

This kind of pure functional style has some definite advantages:

  • It can be easier to debug, since you can just walk up the stack to see what was called and with what arguments; this makes it simpler to pinpoint where bad data came from.
  • It can be easier to write unit tests for, since each function can be called on its own and requires only its argument set; there’s no need for fixtures or any other environment setup.
  • It can be easier to refactor, since you can muck about with the internals of a given function and, so long as you don’t change its signature, be reasonably assured that you haven’t mysteriously broken something else.
  • It makes multi-threaded programming a little bit easier, because you don’t have to worry about things in Thread A modifying bits of program state that Thread B needs to work with (notice that I say “a little bit easier” and qualify “state” to “program state” — if the program is, say, doing database access, it’s still possible that one thread could modify important data, it’s just that the data is external to the program).

But a lot of this is academic; there aren’t a whole lot of pure functional languages, and when people talk about doing “functional programming” in real-world situations they’re rarely talking about pure functional programming. Common Lisp, for example, isn’t a pure functional language, even though Lisp is the patriarch of the functional language family. And OCaml, which is one of the darlings of the trendy functional programming world these days, also isn’t purely functional.

General mish-mash languages

Plenty of languages also support “multi-paradigm” programming; Python and Ruby, for example, both allow you to bounce around between procedural programming, object-oriented programming and functional programming, using each style wherever it best suits what you need to do. Generally these languages offer a few important features:

  • Functions are first-class objects and can be the return values of, or arguments to, other functions. Not having this feature in a language makes functional programming of any sort diffcult, if not impossible (Java and C# people: imagine a world where you could just get a real reference to a method instead of doing indirection with delegates).
  • The language supports closures. This is a tricky topic to explain correctly, but the essence of closures is that you can, for example, have code which generates and returns a function, and which magically “closes” up certain values from the enclosing scope and keeps references to them for use by the returned function, even when they would normally go out of scope before the returned function is called.
  • The language usually — but not always — provides the ability to define “anonymous” functions. These are functions which are not defined by name, but which can be conjured up “on the fly” whenever a function needs to be passed in somewhere.

JavaScript has all three of these features: it supports closures, functions are first-class objects and you can define anonymous functions. This means that, in addition to doing procedural or object-oriented programming, you can easily do functional JavaScript programming.

The case for functional JavaScript

And there are a lot of times where you need JavaScript to be functional, even if you’re not used to thinking of it in those terms. Consider this example snippet of code, which — if you were using the YUI toolkit — would set up an event listener for clicks on an HTML element with an id of ‘myelem’:

YAHOO.util.Event.addListener(
    'myelem',
    'click',
    function(e){
        alert("You clicked the 'myelem' element.");
    });

This is obviously an extremely simple example, but notice three things:

  1. This is a function call.
  2. The final argument is a function.
  3. Not only is it a function, it’s an anonymous function.

If you’ve ever done any serious JavaScript programming, you were probably slinging functions — both named and anonymous — around all the time. Especially when you’re setting up event listeners or specifying more general callbacks, it’s just the most natural way to do things, but I’ve noticed that very few people, even people who write JavaScript day in and day out, realize that what they’re doing is a form of functional programming.

And that four-letter word that’s on everybody’s lips these days — you know the one I’m talking about — certainly encourages a functional programming style. For example, when making a remote call with the Dojo toolkit, a couple of the arguments to dojo.io.bind are functions, and a large number of useful examples use anonymous functions defined on the spot. YUI’s asyncRequest expects an object as one of its arguments, and several of the attributes of that object are, well, functions. Prototype’s Ajax.Request (damn, I had to say it; why’d they have to put “AJAX” in the name?) expects, among the other arguments to its constructor, an object, at least one of the attributes of which is a function.

And, of course, Prototype and JQuery are very heavily functional (JQuery, from what I’ve seen of it, much more so); very nearly everything you do with them is a direct function call, and lots of the functions you’re calling can take functions as arguments.

In other words, once you start looking for it, you’ll start seeing functional programming everywhere in JavaScript.

So?

You’re probably wondering if there’s a point to all of this, and I’m not sure there is. Based on what I’ve been seeing on a few noteworthy programming-oriented news sites, functional programming is enjoying a bit of a renaissance right now, and I know I’m not the only one with an itch to play around in a functional language. But that itch often takes the form of working with an entirely new language, requiring you to spend time not only learning the concepts, syntax and standard library, but also getting a development environment set up for it: an IDE, any compilers, interpreters or runtime environments for the language, standard libraries… just getting the tools you need to play with the language can be a major time sink.

But JavaScript doesn’t have that problem. Text editors which understand JavaScript are free and plentiful, and the standard library plus runtime is built in to your web browser. With certain browser extensions, you can even get a REPL-style playground. And, best of all, JavaScript is an extremely easy language to learn, and odds are good you already have some experience with it. So if you’re thinking of dabbling in functional programming but aren’t sure you want to commit to learning a new language and setting up its associated environment, give some consideration to JavaScript. You might be pleasantly surprised at what you find right under your nose.

Comments

Masklinn
October 11, 2006
#

Javascript is fairly nice for functional purposes, but it has two big (to me) issues:

  • Verbose syntax
  • Anonymous functions in javascript require no less than 12 characters apart from the argument names themselves (function, (), {}). Haskell needs 3 (, ->)
  • Plus if you’re using a functional style, you’re returning values non-stop, and returning values requires 6 more characters (excluding whitespaces)
  • Missing features
  • Javascript has no notion of parallel assignment/tuple unpacking, which makes deconstructing lists or returning multiple values a damn pain (you have to manually deconstruct lists an element at a time)
  • Javascript doesn’t have pattern matching, and pattern matching is probably the hugest boon of “true” functional languages
  • Debugging javascript is a pain, even though Firefox makes it much much nicer
  • Javascript has no real notion of namespaces, modules, imports, … Sure they can be emulated (which much better than PHP), but that’s no replacement for real module objects. Functional style really needs modules/packages/whatever, or it becomes a mess really fast.
  •  Ugh
  • If you don’t “var” your variables, they’re declared as globals. Always. The only way to get warned is either to use JSLint or to active Firefox’ Strict Javascript mode.

To conclude, I really like javascript, and I do love functional javascript much more than object javascript (been duplicating my implementations of filter, map and reduce in pretty much every script I’ve laid my hands on in the last 6 months or so, just because I know I’ll need them one day), but it falls short of being a functional language. Far too short.

BTW you may be interrested by MochiKit for functional-style javascript, it’s inspired by Python and really everything uses functions, there are very few objects generated by the framework itself.

Masklinn
October 11, 2006
#

Dammit, the tentatively nested list failed in the previous post.

Was meant to look something like that:

  • Verbose syntax > * Anonymous functions in javascript require no less than 12 characters apart from the argument names themselves (function, (), {}). Haskell needs 3 (, ->) > * Plus if you’re using a functional style, you’re returning values non-stop, and returning values requires 6 more characters (excluding whitespaces)
  • Missing features > * Javascript has no notion of parallel assignment/tuple unpacking, which makes deconstructing lists or returning multiple values a damn pain (you have to manually deconstruct lists an element at a time) > * Javascript doesn’t have pattern matching, and pattern matching is probably the hugest boon of “true” functional languages > * Debugging javascript is a pain, even though Firefox makes it much much nicer > * Javascript has no real notion of namespaces, modules, imports, … Sure they can be emulated (which much better than PHP), but that’s no replacement for real module objects. Functional style really needs modules/packages/whatever, or it becomes a mess really fast.
  • Ugh > * If you don’t “var” your variables, they’re declared as globals. Always. The only way to get warned is either to use JSLint or to active Firefox’ Strict Javascript mode.
Mark Smith
October 11, 2006
#

Nice article! It doesn’t really surprise me that JavaScript can be seen as a functional language but I’ll certainly play with it the next time I do some web development.

There are a few things I want to bring up, just to be pedantic you understand.

I wouldn’t really agree that Python programmers like to be explicit; if they did wouldn’t they just use a language with type declaration?

In four-five years of Python programming, and after working with most of the languages you mention (and some you don’t) I’ve never once read anyone say Python isn’t OO because it explicitly passes self. To be honest this sounds like you may be misquoting.

Anyway, the reason for self can be quite subtle, but it is powerful. Having an explicit name for the instance is very useful in meta-classes where you shouldn’t use self to refer to the instance - thankfully I’ve been able to avoid Pythons meta-classes for the most part!

Python could be called less OO than [some] languages because primitive types belong to a more restricted set of objects, limiting what you can do with them. No one quite tops Smalltalk though, not yet!

More in tune with this article: self allows you to call methods as if they were functions, passing the instance as an argument if needed. If you combine this with things like Curry, Partial or Compose you can do some really beautiful things :).

I saw a really neat implementation of multiple-dispatch in some code a long time ago, which used this to its advantage. (No, it wasn’t on IBM).

Python’s not perfect; it’s swings and roundabouts.

Lastly, Common Lisp (or almost any lisp language for that matter) is a multi-paradigm language. You can program in any style you want, functional programming is just the nicest :).

Thanks again!

James Bennett
October 11, 2006
#

Mark, here is an example of the “Python isn’t OOFUD. Quoth:

You need to pass “self” as a parameter to all your methods… Does this remind you anything? Right, that’s how we “simulated” object-orientation in C, by passing the address of the current object in first parameter. If anything, this shows that Python is not object-oriented, and this flaw is a simple illustration of Python’s old age (it was not object-oriented when it was created, more than fifteen years ago).

That sort of stuff gets slung around all the time by idiots who don’t know any better.

James Bennett
October 11, 2006
#

Also, Python’s primitive types have been getting better; they’ve been proper classes for a while, and can be subclassed, etc. And if you really want to fiddle with them at runtime, you can, but it’s not something that’s recommended or easy.

And take a look in Django’s internals sometime; there’s lots of functional Python goodness going on in there.

John Resig
October 11, 2006
#

Masklinn: JavaScript 1.6 takes care of your filter, map array comments. JavaScript 1.7 handles destructuring and your scope issues. JavaScript 2.0 has a whole namespace system.

  • 1.6: http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6
  • 1.7: http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7
  • 2.0: http://www.mozilla.org/js/language/evolvingJS.pdf

So while the current implementation is “lacking” - it’s absolutely moving in a more functional direction.

Masklinn
October 11, 2006
#

Masklinn: JavaScript 1.6 takes care of your filter, map array

> comments. JavaScript 1.7 handles destructuring and your scope
> issues. JavaScript 2.0 has a whole namespace system.

I do know all that (by the way the part on map/filter/reduce wasn’t a criticism of JS, I was just saying that I use them a damn lot), but while JS1.6 is supported in Firefox 1.5 and JS1.7 will (partially) be available in Firefox 2.0, how long will we have to wait till we can use them out of XUL/Firefox extensions scripting? How long till Safari, Opera and Internet Explorer implement all that and we can actually use them “in the real world”?

Having the language finally move forward and having some people trying to correct its warts is of no use if the language’s new features stay unimplemented…

Yaa101
October 11, 2006
#

My comment is:

Thanks for being specific, I will be somewhat more general. I first want to state that all living computer related languages are functional and all are used in their context. Though their context is fading.

I started programming on my commodore 64, this was mainly 6502 assembly and later with help of the venerable turbo c 2.0 on the PC, nothing useful came out of this, you can compare it with doodling, however it gave me the foundation of understanding the underlaying hardware. Very much did the hardware and the lack of power dictated the languages used, languages like Perl or Python doesn’t get you very quick to where you want to go on a Commodore or a 8086.

Later I started making some web pages and found it hard to accept that only static writing was on such page so I went to find a programming language that bridged that gap. I found several of them and stuck with PHP, I could have chosen Perl or ASP at that time but the available platform for me as non-professional at that time was Apache and Linux, so again platform demanded me to use certain languages available for that platform. However by that time the hardware was powerfull enough to run interpreters and late binding compiling languages. This is also where a lot of my language is better than yours envy started, before that the hardware platform and manufacturer just dictated what language you had to learn.

Nowadays it is fashion to port every available language to any platform, on one part that is good because it gives people to stay within their preferred language environment, but the bad part is balkanization of camps of this language or that language. As debates get more fierce and more politicized you probably also will see lobby efforts to forbid this or that language.

What you see happening is a strange sort of emancipation of the software field that has wriggled itself out of stronghold of hardware and now it will impose on itself larger restrictions than hardware ever did. This will only get worse with virtual machines like VMWare servers, don’t get me wrong, these things are wonderful, but on the longer run they tend to make hardware distinctions even more vague as on most hardware platforms the looks and feels will be exactly the same.

Shortly said, lack of domination from the outside will spark a fierce political landscape on the inside. I myself do not join this debate as I am from a generation of programmers that had to be practical first as there was no room to do things elegant apart from exotic languages on exotic platforms that were only affordable by a happy few. I tend to see room for all ideas and all languages and use the ones that make me able to get the job done within reasonable time.

Time given by what economy grands you is the biggest bug ever in all software.

Jake Ham
October 13, 2006
#

Interesting article!

In Python 2.5, they released a feature called partial function application. This gives Python the ability to pass functions as agruments in a functional programming style way. You can check it out here:

http://docs.python.org/whatsnew/pep-309.html

David Baelde
October 19, 2006
#

Hi,

Javascript does sound functional, and I was happy to consider that at first. But I recently ran accross some troubles and discovered the real way JavaScript handles scoping: no block scoping, and (even worse) the use of “var” in a function makes every instance of the variable local, even those who come before the “var”… I was very much disappointing! Details on http://lambda-the-ultimate.org/node/1775

Add a comment

You may use Markdown syntax in your comment, but raw HTML will be removed. By posting a comment here, you are agreeing to the terms of my comment policy.