Hacker News new | comments | show | ask | jobs | submit login

It's a nice clean language that fits the event-driven paradigm better than most. When every function is an automatic closure, things are much easier.

I'm really at a loss as to how people seem to just swallow this claim without question. What's so special about Javascript's closure support vs Perl, Python, Ruby, PHP, Lua, C#, Lisp, Erlang, or ${all other functional languages}? What's Node.js got over Twisted, POE, EventMachine, or every single thing ever written in Erlang?

Most languages used in web development have closures. A large number of them have event-based frameworks. I found quite a few other candidates poking around in the other languages but lacked the skills or time to evaluate whether they were also structured like Node.js.

I don't mind the existence of Node.js, but the people claiming it's "better than most" make me wonder if they've ever used the "most" they claim it's better than. Erlang in particular. That's something that's "better at the event-driven paradigm than most". Javascript has nothing on Erlang, Javascript's just another C-derived manually-chop-your-code-up-to-work-with-callbacks monstrosity by comparison.

Edit: No, if I were going to pitch Node.js, I would pitch it as "Use the same language on both the client and the server; it's adequate on the client, it's adequate on the server." OK, "adequate" isn't the best pitch but it's honest. The stupidest thing about web development today is needing to know three languages (HTML + browser quirks counts as roughly as complex as a language, client-side JS, server side not-Javascript language) just to get your foot in the door. Having the same language on client and server will probably provide some interesting capabilities, such as the thing mentioned in another comment where your comment formatting code can be run in either place (show on the client exactly what they'll get if they submit, run on the server to validate it), or validation code that is guaranteed identical on both client and server, or several other interesting things I can imagine where you can play games with exactly where something is run. Server-side Javascript just shouldn't be pitched as a "uniquely capable" language in a field full of PHP, Perl, Python, and Ruby... "uniquely capable" is Erlang or a the Seaside framework, not Yet Another (Dynamic) Algol Variant.

Something that's different, at least from POE, EventMachine, Twisted is that it is attempting non-blocking purity. You can snub your nose at this but it turns out to be very important. It ends up abstracting away a problem in a way that EventMachine or Twisted will never be able to do simply because of the existence of massive amounts of blocking Ruby and Python libraries. The programmer simply doesn't have to know what non-blocking I/O is - they don't have to know that if they do "node script.js < hugefile" - that STDIN_FILENO cannot be selected on.

Erlang is different. Node presents a different programming model than Erlang - Node handles thousands of connections per process - and keeps itself close to the metal. Erlang is it's own operating system handling one connection per processes but allowing very many processes. Is Node's model better? Well at the moment it's incomparable since Erlang is very much a solid, production ready system and Node is not more than some dude's hack. But supposing that Node becomes stable and usable at some point, a major advantage of the Node model is that for the first 10,000-1,000,000 concurrent connections the programmer doesn't have to know anything about concurrency - a single process will just handle it. There is no forking or IPC - it's just synchronous events and callbacks. In Erlang you have to think about about IPC on the first connection. The Erlang-model might turn out to be the wrong level of process granularity. Maybe the right level of process granularity is how computers are already designed: 10,000-1,000,000 connections per process, use one per core.

I also wish for less hype around the Node project but I think you're short changing it by saying it's same thing as Twisted but in Javascript instead of Python. The main selling point is not that you can run the same code on browser and server. The main selling point is that you don't have to know what you're doing, at least for the first 10,000 concurrent connections.

"There is no forking or IPC - it's just synchronous events and callbacks. In Erlang you have to think about about IPC on the first connection. The Erlang-model might turn out to be the wrong level of process granularity. Maybe the right level of process granularity is how computers are already designed: 10,000-1,000,000 connections per process, use one per core."

Also false. An Erlang "process" is not an OS process. It already works the way you say, except it can use multiple cores simultaneously. Automatically. Node.js has nothing on Erlang except a familiar syntax. Nor does IPC come up like some kind of blocker; it's baked into the core and quite natural, often all wrapped up behind a simple function call.

And let's not even talk about the baked-in clusterable Mnesia database or the OTP library, which Node.js can only dream about. (Erlang isn't just multicore, it's pretty easy to make it multi-system.) Or how Erlang has code replacement (the Node.js complaint of the day) built right in to the core, where it really has to be for it to work. And Erlang laughs at your "non-blocking purity"; in Erlang, you can call sleep and it won't block anything! No special support needed, no magic from the user, no arranging things in callbacks manually (how 1980s). Try that in Node.js.

It's actually impossible for Node.js to do some of these things because you have to start with them.

You don't understand how Erlang works. That's fine, except you started to criticize it. I refer back to my previous comment that the people hyping Node.js don't seem to have used the competition. Maybe my problem is that I have used the competition, quite extensively. Come to think of it, I've yet to hear anyone say "Gosh, I was using Erlang but Node.js is just so awesome I had to switch!:" That probably says something important.

You should read my reply again (or maybe for the first time) and comprehend. I did not say nor imply that I think Erlang's processes are OS processes. Sorry for not using quotes ('process') if that's what has confused you so deeply.

You can hardly expect me to read your mind on that point when you bury it in so many other wrong ideas about Erlang, which I note you do not challenge.

> I also wish for less hype around the Node project

I'm tremendously amused that you write this when every other poster on HN is desperately trying to generate hype for their project/company.

Yeah, Lua and Erlang in particular seem better suited to this role. Erlang's whole model is fundamentally event-driven, and Lua is remarkably similar to Javascript, only without the design errors made permanent, and with a better JIT compiler.

Javascript's already closely tied to the web, though, and it gets plenty of word-of-mouth since web developers already know it. That will probably beat any technical advantage.

Python has no true anonymous functions.

Ruby is just a mess in this regard,even if you can arguably do anything you want in the end : http://innig.net/software/ruby/closures-in-ruby.rb

On the other hand, javascript has a simple, no bullshit syntax for functions. If you want a function to be anonymous, just don't give it a name.

Erlang and Lua obviously have true anonymous functions and closure support.

JS has three epic wins going for it, that cannot be matched together by another language:

  * A shitton of people are already using it on the daily
  * All of the existing code written in it is event-driven
  * It's got prototypical inheritance, and some people
    actually use it instead of bludgeoning in classicism

* A shitton of people are already using it on the daily

This is actually a problem. Majority of that shitton use js without knowing what they are doing. It's a copy-pasted code for some client-side validation. Even the so-called framework-users (jQuery and Prototype) depend blindly on plugins for their job.

You aren't wrong, and I find Protoype.js incredibly depressing (see my third point).

But the point is that you're not going to get fired for choosing JS on the server. It has curly braces! Your boss isn't so worried about hiring.

I see where you are going. Getting a large pool to pick from isn't going to be a problem.

Your second and third points have been matched by Erlang, and for longer too.

Yeah, but it is the first point that matters, and when matched with two and three the real power comes.

1. People are forced to use javascript.

2. There are a lot of people who use erlang.

1. Good point. I was definitely forced to use it. Nowadays it's probably more like a first taste language for most new developers though.

"What's so special about Javascript's closure support vs Perl, Python, Ruby, PHP, Lua, C#, Lisp, Erlang, or ${all other functional languages}?"

Javascript has java-like syntax. Heck, it even bears half the name even if the language has almost nothing to do with Java. Did you know that the first version of Javascript was actually a scheme variant but they decided to conceal its identity so it would appeal to the masses?

It's stupid that a familiar syntax is one of the foremost considerations in the mass adoption of a language, but that's reality for you.

(PS: I'm a Common Lisp fanatic so I'm acutely aware of this syntax problem.)

Well Python's lambda's kinna suck for one. As far as I know, Python, Ruby, and PHP all suffer from the fact that all functions are not first class. Also Javascript's prototypal inheritance is pretty neat. I'm not saying js is a "great" language, it's not with out it's crufty bits, but it's a nicer language than most people give it credit for.

"Well Python's lambda's kinna suck for one."

Not really relevant in this context, as naming things isn't that big a deal. Lambdas are only needed for one-liners and they serve that purpose fine.

"As far as I know, Python, Ruby, and PHP all suffer from the fact that all functions are not first class."

Definitely false for Python, Ruby actually has multiple kinds of first-class functions (for better or for worse, I am assured that in practice it's not a problem), recently false for PHP (http://en.wikipedia.org/wiki/PHP#5.3_and_newer ), and to save time, also false for Perl, Lua, ${all functional languages} (pretty much by definition, there), and false for C# as of 3.0.

If you want to play "oh but the support is quirky", Javascript has its own quirks on the closure front:

    var i;
    var funcs = [];
    for (i = 0; i < 5; i++) {
        funcs.push(function () { alert(i) });
What does that alert?

Mind you, that's only a quirk and I wouldn't crucify the language for it, it's arguably correct and sensible once you understand it. The again, Python's scoping is arguably correct and sensible once you understand it, too, but people don't cut it much slack for that.

(The answer is 5 by the way. Compare with Perl, which can actually close on a variable created inside a scope in the function, instead of having just one function-level scope like Javascript. Compare with Python, which does what Javascript does.)

Actually you could say that functions in C# have been first-class since version 2.0.

We of course need to define what first-class is ... if it's the ability to have higher-order functions, than 2.0 fits. C# 3.0 only adds a light-weight syntax for anonymous delegates plus the really kick-ass ability to get a syntax tree of that method instead of the method's reference (on which Linq is based) ... and I really wish other languages add this capability (it was possible in Ruby 1.8.x, but it's not anymore in Ruby 2.0).

Python kicks ass in regard to first-class functions ... and it leverages that ability with decorators. People using other languages go through great pain to have AOP capabilities (for example), but in Python it only takes like 10 minutes to add a couple of utilities to do whatever you want.

The only frustration I have with it is the lack of multi-line anonymous blocks, but Python is so flexible you can add that using "with" block hacks, like described here ... http://billmill.org/multi_line_lambdas.html

Also, once you understand dynamic-scoping ... it's really not that big of a deal to deal with the situation described above. It's just different.

I like the lexical-scoping in Perl as it prevents all kinds of errors ... but in Python I have real exception-handling, and a kick-ass debugger console just by adding "import ipdb; ipdb.set_trace()" anywhere I want.

Erm. Yeah I know for a fact that not ALL PHP functions are first class. Which was all I was saying. PHP does have lambda, but not EVERY function is a lambda.

Can someone explain to me why the answer is five? Appreciated.

There are two ways a for loop like that implemented:

The first way, which I prefer, is to make the binding of i to its value inside the loop body, this way you get a nice fresh binding on each loop iteration, so if you iterate the loop 5 time you get 5 bindings.

The other way, which I loathe but is still an arguably "correct" way to do it, is to make one binding of i outside of the loop and then modify it on each loop iteration, so no matter how many iterations of the loop you have, there's only one binding.

As far as I'm concerned, the first implementation is obviously the better one because the instances where this benefits you come often while the instances where the second implementation benefits you is very rare and unidiomatic. I think the second implementation is used for better performance but that's a mistake.

I had this problem of perceptions when I switched from Common Lisp's Loop to Iterate. Loop, for all its many big shortcomings, had the decency of making a fresh binding on each new iteration, though IIRC the standard specifies that bindings can be established outside or inside the loop context. When I want to make a closure based on the value of an iterated variable with Iterate I have to do an explicit binding...

i is a mutable variable declared in the enclosing scope. The for loop mutates it, and each anonymous function closes over i. After the loop is finished (when func[3]() is called, i is equal to 5.

I'm not sure what makes this a "quirk" since this is exactly what closures should do: they maintain a reference to the variable from the enclosing scope. This is also the behavior of a fairly classical example of closures in scheme.

I still remember when Javascript was a fairly ugly language that felt like the PHP of client-side programming.

I revisited Javascript a few years ago and I was pleasantly surprised. It's come a long way, and it does make event-based programming easy.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact