简体   繁体   中英

reinventing the wheels: Node.JS/Event-driven programming v.s. Functional Programming?

Now there's all the hype lately about Node.JS , an event driven framework using Javascript callbacks. To my limited understanding, its primary advantage seems to be that you don't have to wait step by step sequentially (for example, you can fetch the SQL results, while calling other functions too).

So my question is: how is this different, or better than just functional languages, like CL, Haskell, Clojure etc? If not better, then why don't people just do functional languages then (instead of reinventing the wheel with Javascript )?

Please note that I have none experience in either Node.JS nor functional programming. So some basic explanation can be helpful.

Having read through the Node.JS docs (and the nice slide deck ), I think the other answers here are missing the point about it: Node.JS is based on the idea that the style of writing programs where we expect them to block on I/O is wrong, and that instead we should initiate I/O (such as reading a database, or reading a socket) and pass along a function to handle the result of the I/O along with the request.

So rather than do this:

var result = db.query("select.."); // blocking
// use result

Node.JS is based on the idea of doing this:

db.query("select..", function (result) {
    // use result
});

The authors (of Node.JS) point out that this way of programming is very awkward in many systems as the languages don't have closures or anonymous functions and the libraries are primarily blocking I/O. However, Javascript supplies the former (and programmers are used to it given how JS is used in an event like manner in the browser), and Node.JS fills in the later: being an entirely event driven I/O library with no blocking calls at all.

How does this relate to functional programming? All functional programming languages provide closure constructs powerful enough to do what Node.JS is trying to do with Javascript. Most make it even easier to code, as passing closures is generally fundamental to the language.

As for Haskell, using Monads, this sort of thing could be very easy to construct. For example:

doQuery :: DBConnection -> IO ()
doQuery db = do
    rows <- query db "select..."
    doSomething rows
    doSomethingElse rows

These very sequential, imperative lines of code are actually a sequence of closures under control of the IO monad. It is as if in JavaScript you had written:

db.query("select...", function (rows) {
    doSomething(rows, function () {
        doSomethingElse(rows, function () { /* done */ })
    })
})

In essence, when writing monadic code in a functional language, you already are writing it in the form the Node.JS authors want us to write: Where each step of the sequential computation is passed as a closure to the prior one. However, look how much nicer that code looks in Haskell!

Furthermore, you can easily use concurrent Haskell features to achieve this non-blocking operation easily:

forkQuery :: DBConnection -> IO ThreadId
forkQuery db = forkIO $ do
    rows <- query db "select..."
    doSomething rows
    doSomethingElse rows

Don't confuse that forkIO with the expensive process fork you're used to, or even OS process threads. It is basically the same light weight thread of execution that Node.JS is using (only with somewhat richer semantics). You can have 1,000s of 'em just like Node.JS aims for.

So, in short - I think Node.JS is building on a facility that exists in JavaScript, but that is much more natural in functional languages. Furthermore, I think all the elements that are in Node.JS already exist in Haskell and its packages, and then some. For me, I'd just use Haskell!

I don't really know about Node.JS either, but I don't really see any striking similarity between it (from your description) and functional programming. From your description, Node.JS seems to be aimed at aiding asynchronous programming -- as you state "you don't have to wait step by step sequentially", you can do other tasks as one long-running task does its thing.

Functional programming is completely orthogonal to this -- ie it doesn't really have any link to asynchronicity. You can have one without the other, or both together, or neither of them. Functional programming is about eliminating side-effects in your programs, and about allowing functions as first-class members of the language, to be manipulated and composed similarly to other values.

This isn't really "reinventing the wheel." Javascript isn't really a functional language per se, but it was based on Lisp and this is the sort of thing it was designed to do. Javascript is really stronger as a Lisp-ish functional language than it is as an OO language in my opinion. That's why frameworks with strongly functional* designs like jQuery fit the language so well.

(* Note: Not pure, obviously, but functional in much the same way as Scheme.)

I haven't used node.js yet, but I'm definitely interested in it and will be trying it out soon. There are already lots of great answers about functional programming and such here, so I won't go into that.

You ask why not use some other language on the server, such as haskell, Closure, etc. For me, the attraction of node.js over others is that it IS javascript. My applications are already heavy in javascript on the client, so it means I could work in one language on both the server and the client.

My hope is that this will streamline and simplify development because I won't need to be switching contexts so drastically. There might even be some reduction in work if some logic that is used both on client and server could be shared (perhaps form validation code and the like).

Javascript's key role in node as a webserver is that it is largely event driven.

I believe functional programming has advantages for concurrency, due to immutability among other things.

not sure how event driven other functional languages are, just wanted to highlight it as part of the advantages of node.

One of the main benifits with the gap between the client and the server shrinking is the ability to reuse code on the client and the server. For instance if you want to have a rich and dynamic AJAX website for modern browsers and a stripped down version for older browsers you can use the same display code to format incomming data on both the client and the server.

Other benifits with this include the HTML5/Google Gears/Adobe Air ability to have a local storage DB and server to run web apps offline, you can have code that would traditionally be on the server stored locally for when the server is not available.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM