views:

491

answers:

4

I've been working with node.js for awhile on a chat app (I know, very original, but I figured it'd be a good learning project). Underscore.js provides a lot of functional programming concepts which look interesting, so I'd like to understand how a functional program in javascript would be setup.

From my understanding of functional programming (which may be wrong), the whole idea is to avoid side effects, which are basically having a function which updates another variable outside of the function so something like

var external;
function foo() {
   external = 'bar';
}
foo();

would be creating a side effect, correct? So as a general rule, you want to avoid disturbing variables in the global scope.

Ok, so how does that work when you're dealing with objects and what not? For example, a lot of times, I'll have a constructor and an init method that initializes the object, like so:

var Foo = function(initVars) {
   this.init(initVars);
}

Foo.prototype.init = function(initVars) {
   this.bar1 = initVars['bar1'];
   this.bar2 = initVars['bar2'];
   //....
}

var myFoo = new Foo({'bar1': '1', 'bar2': '2'});

So my init method is intentionally causing side effects, but what would be a functional way to handle the same sort of situation?

Also, if anyone could point me to either a python or javascript source code of a program that tries to be as functional as possible, that would also be much appreciated. I feel like I'm close to "getting it", but I'm just not quite there. Mainly I'm interested in how functional programming works with traditional OOP classes concept (or does away with it for something different if that's the case).

A: 

So 2 things to point out ,

  1. In your first example your variable would not be leaking into the global area and is the way it should be done , try to never use variables without declaring them i.e. test = 'data' would cause data to leak into the global area.

  2. Your second example is correct as well , bar1 and bar2 would only be declared on the Foo object.

Things to keep in mind try not to overuse prototyping since it applies to every object that you create , this could be extremely memory intensive depending on how complex your objects are.

If you are looking for a app development framework , have a look at ExtJs. Personally I think it would fit perfectly into the model you are trying to develop against. Just keep in mind how their licensing model works before getting heavily invested in it.

RC1140
thanks for the comment. node.js is server-side javascript, so I don't think extJS is meant to work there, but I may be mistaken. I'm more interested in just best practices for applying the functional programming model to javascript in general. I know how to build the app if I just use traditional object oriented design (good point on over prototyping though), but I want to know how to attack it using the concepts of functional programming as much as I can.
+1  A: 

I think, http://documentcloud.github.com/underscore/ should be nice fit for what you need - it provides the most important higher-order functions for functional programming and does not has client-side functions for DOM manipulation which you don't need for server side. Though I don't have experience with it.

As a side note: IMHO primary feature of functional programming is Referential transparency of a function - function result depends only on its parameters - function does not depend on changes on other objects and does not introduce any change except its result value. It makes it easy to reason about program's correctness and very valuable for implementing of predictable multi-threading (if relevant). Though JavaScript is not the bet language for FP - I expect immutable data structures to be very expensive performance-wise to use.

Alexey
Yes, I'm using underscore.js currently and I've used it to eliminate all of my for loops so far.That's kind of the key to FP as I see it as well. The idea of just passing new objects to functions as mentioned by brian below really opened up a block I was having on how to deal with it. I'll see how it performs. Node.js / V8 seems really fast from everything I've read so far, so it'll be interesting to see if this technique works as well.
+2  A: 

You have to understand that functional programming and object oriented programming are somewhat antithetical to each other. It's not possible to both be purely functional and purely object oriented.

Functional programming is all about stateless computations. Object oriented programming is all about state transitions. (Paraphasing this. Hopefully not too badly)

JavaScript is more object oriented than it is functional. Which means that if you want to program in a purely functional style, you have to forego large parts of the language. Specifically all the object orient parts.

If you are willing to be more pragmatic about it, there are some inspirations from the purely functional world that you could use.

I try to adhere to the following rules:

Functions that perform computations should not alter state. And functions that alter state should not perform computations. Also, functions that alter state should alter as little state as possible. The goal is to have lots of little functions that only do one thing. Then, if you need to do anything big, you compose a bunch of little functions to do what you need.

There are a number of benefits to be gained from following these rules:

  1. Ease of reuse. The longer and more complex a function is, the more specialized it also is, and therefore the less likely it is that it can be reused. The reverse implication is that shorter functions tend to more generic and therefore easier to reuse.

  2. Reliability of code. It is easier to reason about correctness of the code if it is less complex.

  3. It is easier to test functions when they do only one thing. That way there are fewer special cases to test.

Update:

Incorporated suggestion from comment.

Update 2:

Added some useful links.

KaptajnKold
I disagree. JavaScript is actually more functional than object-oriented. It has closures, first-class functions, it lacks classes and inheritance. Syntactically, it's more like Java than Lisp but overall actually shares more in common with the latter.
Brian McKenna
You're wrong: JavaScript has both classes and inheritance (but maybe not in the style you're used to). And most if its datastructures are mutable which puts it apart from all purely functional language. I disagree strongly with the notion that it is more like Lisp than it is like Java.
KaptajnKold
Adam, I very agree with the rules you stated. it also would be valuable to add rationale (or link to) why the rules are really valuable. IMHO: 1. easy to reuse the code 2. reliability of code (easy to reason about correctness of the code) 3. easy to test the code
Alexey
I think JavaScript better suites for OOP paradigm then FP.
Alexey
@KaptajnKold, sure, you can use some of JavaScript's features in place of classes and classical inheritance but that doesn't meant JavaScript *has* classes and classical inheritance (you're just using prototypes). You can even tack on some encapsulation but still, you're just using prototypes to create object-oriented concepts. It works for a lot of people and that's fine (probably because it works *well*). In the end, you'll find that JavaScript is prototype-based and *not* fundamentally object-oriented at all.
Brian McKenna
@KaptajnKold, sorry, I also wanted to point out that most data structures in Lisp are mutable, that doesn't make it object-oriented.
Brian McKenna
@Brian Why do you not think prototype based inheritance constitutes "real" object orientation? Do you also thing that Go is not object oriented because it doesn't have inheritance _at all_? I would argue that it's the encapsulation of functions _and state_ that makes a language object oriented. Re. Lisp: I stand corrected. Still, most languages considered to be purely functional do not have mutable data structures.
KaptajnKold
@KaptajnKold I can see your point. No, I would not call Go object-oriented. I think you're describing class-oriented, not object-oriented features (class-orientation is just one important part). Using JavaScript's prototypes it's possible to create inheritance, abstractions, polymorphism, encapsulation, etc. which are object-oriented features. In JavaScript these are all just *emulations* of classical object-oriented languages. By itself, JavaScript is not an object-oriented language but it can be made to work like one. If it works like one, doesn't that make it one? Good point.
Brian McKenna
@Brian I still think you misunderstand what exactly makes a language object oriented, but I guess we're not going to agree on this. I just wanted to point out that the creators of Go themselves call it "a profoundly object oriented language. Arguably more so than Java" (citing from memory from the tech talk on golang.org). I know, appeal to authority is a weak form of argument, but I give a lot of credit to the opinions of these guys.
KaptajnKold
@KaptajnKold I also respect the Plan9 guys that have created Go. I think they're referring to the fact that Go acts very similar to Smalltalk in regards to objects. Smalltalk is regarded as the creator of object-orientation but the term has since changed significantly. I think JavaScript would quite possibly be considered object-oriented by the original definition.
Brian McKenna
@Brian According to you, what is the "original definition" of object orientated programming? And what is the current one? I looked at the articles for "Object Oriented Programming", "Functional Programming" and "Prototype-based programming" on Wikipedia, and they all seem to align with my point of view.
KaptajnKold
I think we need to distinguish between "purely functional" and merely "functional." If we require purity to be considered functional, that throws out the whole ML family, the whole Lisp family, Erlang — pretty much everything but Haskell and a few esoteric languages.
Chuck
@KaptajnKold SmallTalk's object orientation is what I consider to be an original version: http://en.wikipedia.org/wiki/SmallTalk#Object-oriented_programming
Brian McKenna
+9  A: 

You should read this question:

http://stackoverflow.com/questions/145053/javascript-as-a-functional-language

There are lots of useful links, including:

Now, for my opinion. A lot of people misunderstand JavaScript, possibly because its syntax looks like most other programming languages (where Lisp/Haskell/OCaml look completely different). JavaScript is not object-oriented, it is actually a prototype-based language. It doesn't have classes or classical inheritance so shouldn't really be compared to Java or C++.

JavaScript can be better compared to a Lisp; it has closures and first-class functions. Using them you can create other functional programming techniques, such as partial application (currying).

Let's take an example (using sys.puts from node.js):

var external;
function foo() {
    external = Math.random() * 1000;
}
foo();

sys.puts(external);

To get rid of global side effects, we can wrap it in a closure:

(function() {
    var external;
    function foo() {
        external = Math.random() * 1000;
    }
    foo();

    sys.puts(external);
})();

Notice that we can't actually do anything with external or foo outside of the scope. They're completely wrapped up in their own closure, untouchable.

Now, to get rid of the external side-effect:

(function() {
    function foo() {
        return Math.random() * 1000;
    }

    sys.puts(foo());
})();

In the end, the example is not purely-functional because it can't be. Using a random number reads from the global state (to get a seed) and printing to the console is a side-effect.

I also want to point out that mixing functional programming with objects is perfectly fine. Take this for example:

var Square = function(x, y, w, h) {
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
};

function getArea(square) {
    return square.w * square.h;
}

function sum(values) {
    var total = 0;

    values.forEach(function(value) {
        total += value;
    });

    return total;
}

sys.puts(sum([new Square(0, 0, 10, 10), new Square(5, 2, 30, 50), new Square(100, 40, 20, 19)].map(function(square) {
    return getArea(square);
})));

As you can see, using objects in a functional language can be just fine. Some Lisps even have things called property lists which can be thought of as objects.

The real trick to using objects in a functional style is to make sure that you don't rely on their side effects but instead treat them as immutable. An easy way is whenever you want to change a property, just create a new object with the new details and pass that one along, instead (this is the approach often used in Clojure and Haskell).

I strongly believe that functional aspects can be very useful in JavaScript but ultimately, you should use whatever makes the code more readable and what works for you.

Brian McKenna
+1 good answer.
Anurag
thanks for your reply and the helpful links. I really like the idea of just passing new objects to my functions and having them act on it. That was an aha! moment for me.The one thing I was still struggling with fp in general, is keeping functionality together code wise. With OO, it's easy because most everything is a method off of the class (ie car.startEngine(); car.applyBrakes();). With FP, I think I can do a similar thing by using a namespace though and just having my methods require an object as the first argument. so var car = {}; car.startEngine = function(carObj) {}
@user321521, why not to put the function into the prototype of the object you pass to it? Separating data from operations does not make the code more or less FP. It's quite orthogonal.
Alexey
@Brian What you call an _object_ in the above example is not so much an object as it is a struct or a tuple, by which I mean it is purely a _data_ type. Objects (as in Object Oriented) are encapsulations of data _and methods_ and they are characterized by the fact that they can change state what you call methods on them. Now, whatever you choose to call that, it's a concept that permeates JavaScript and one that you'll have to do without if you choose to pursue a purely functional style.
KaptajnKold