

Fogus: Node.js should become its own language - evjan
http://blog.fogus.me/2011/04/12/node-js-is-dead-long-live-node/

======
travisglines
As someone who has spent the last six months coding in Node.js, I completely
disagree with this notion.

One of my favorite advantages of Node is in fact that it is based on
javascript. When building my application I can share code between client/sever
side (string formatting methods for example) and don't need to do any mental
context switching when it comes to languages. I've developed in javascript for
years and all that I have learned doesn't go out the window here, all I need
to do is learn how to use a few libraries.

The "faults" of javascript are primarily inexperience with event looped
architectures that use callbacks (people complaining about having to use
callbacks and the spaghetti code messes they make), people remembering the
past horrible browser implementations of it (where something would work/be
fast in one browser and not another ... Internet Explorer I'm looking at you)
and confusion over how prototypical languages work vs. standard OOP.

Callbacks aren't that bad and a few extra nesting levels shouldn't create
chaos in your code. Since its based entirely off of one javascript
implementation (V8) the cross browser stuff is gone. How it handles OOP is
different, just watch these videos first and you'll be fine:
<http://www.yuiblog.com/blog/2007/01/24/video-crockford-tjpl/>

As far as speed goes it gets huge benefits by being javascript. Every time the
Google coding machine feels like making V8 a little faster, Node gets faster
too.

Yes its different, no its not worse ... its better but takes some getting used
to.

~~~
scott_s
I think the fundamental objection fogus has is that the language does not
support the programming model. For example, I _can_ program object-orientedly
in C, but that language does not help me do it. I have to do much of the work
myself. So you _can_ program in JavaScript in an event-based way using
Node.js, but JavaScript itself does not help you much in doing so. It requires
that you do most of the work yourself - work that is mechanical, and basically
requires that you be a human compiler.

Disclaimer: I don't program in JavaScript or Node.js. So I'm talking from
conceptual understanding, not experience.

~~~
DTrejo
_It requires that you do most of the work yourself - work that is mechanical,
and basically requires that you be a human compiler._

It would be a good idea to write some JavaScript before you make statements
like these with so much conviction.

~~~
scott_s
Fair enough, but the examples I've seen look like continuation passing style
(<http://en.wikipedia.org/wiki/Continuation-passing_style>), which is
something we know how to abstract behind language syntax and semantics. In
what way am I wrong?

~~~
dionidium
Programming in an "event-based way" is a huge part of writing traditional
JavaScript in the browser. You're handling user events, Ajax responses, the
page load itself. And JavaScript's first-class functions and closures are
extremely well-suited to the task.

~~~
scott_s
Ah, yes, you are correct. Then consider for the sake of discussion that I said
"asynchronous."

------
Cushman
_Why would you write this: [long_io_operation with callback] When you can
instead write this: [long_io_operation without callback]_

Off the top of my head, I'd say because "var result = long_io_operation(req);"
is not only not self-documenting but actively _deceptive_ if long_io_operation
is an asynchronous call.

I'm not sure I see what's to be gained by pretending closures don't exist.

~~~
metabrew
It's not deceptive if you have a preemptively multitasking runtime that you
trust (like the Erlang VM); it's a much more natural way of writing code.
Single-threaded, event-driven callback spaghetti makes code harder to read,
and inherently means _more_ code.

If someone took v8, added lightweight coroutines, and wrote a preemptive
scheduler for it, I bet you could massively reduce the SLOC count for large
node.js apps.

~~~
sovande
> It's not deceptive if you have a preemptively multitasking runtime that you
> trust

That may be so, but since Javascript is inherently single threaded _and_ this
is about javascript I agree with Cushman that it is indeed deceptive.

~~~
jerf
But we _aren't_ talking about Javascript. It's about a theoretical replacement
language.

Also, the reason you care about the "synchronicity" in the first place is
because your environment forces you to care! When it all Just Works (TM), you
don't care whether it's "synchronous" or not. That's a deficiency in your
language, not a feature.

I'm not theorizing. I program in this sort of language all the time. You worry
much more simply about how long something will take, which you can never not
worry about, rather than how many bits are "synchronous".

~~~
sovande
> But we aren't talking about Javascript. It's about a theoretical replacement
> language.

Apparently the plan is to implement this "theoretical replacement language" in
javascript using node.js

<https://github.com/fogus/funode/blob/master/src/funode.js>

------
jerf
Since fogus is responding here: Other than hitching your wagon onto the
fantastic hype storm that Node.js has generated, which I must say is a good
move overall, reading your target description, why not start with Haskell or
Erlang? You could start from there and mutate out but actually have a library
base to start from. Or one of the languages sitting on top of Erlang like
Reia. (Or discover that you don't need to mutate away after all.)

Starting from scratch is going to be difficult at this point; by the time you
even have a half-decent stack you're going to be way behind.

(At the very least... you _do_ realize this has been done and you don't have
to start from scratch, right? Rather a lot of Node.js users have exactly the
cognitive holes I'd expect from not knowing that Node.js is at best "keeping
up", rather than being anything like cutting edge. And I'd say this style of
programming was actually on its way to the dust heap of history before being
brushed off and gotten a shiny new coat of paint sprayed on... it really
doesn't work very well....)

~~~
MrMan
I will upvote you if you explain what you mean by the last part about "this
style of programming" previously being on its (it's? anyone) way out. Do you
mean an asynchronous style using callbacks?

~~~
jerf
Yes. Asynchronous style using callbacks has been done many, many, many times,
and it really doesn't work very well. It does small things quickly, but have
you noticed the number of complaints about how Node.js produces spaghetti code
increasing lately, quietly and slowly but steadily? It's still buried under
the hype, but expect it to get worse. And not "get worse before it gets
better", just... get worse.

I laid it out more at <http://news.ycombinator.com/item?id=2370303> .

Javascript doesn't particularly bring any abstraction capabilities to the
table that Perl (POE, Event::Lib, IO::Async), Python (Twisted), or Ruby
(EventMachine) doesn't, and current Javascript is actually deficient in the
abstraction department by comparison. (The latest ECMAscript spec can compare
to them, so Javascript will get there. Something like Python generators allow
you to string together a couple more tricks together before the complexity
becomes a problem, and Javascript will eventually have this.) They all result
in programs that end up the same way. There are some tricks you can play that
improve the situation a bit over raw callbacks, like trying to sequence them,
but composing these tricks together gets harder and harder the fancier you
get.

None of those libraries really took off and some of them I know had way more
effort poured into them than Node.js has seen yet, like Twisted. And it's
because the style, combined with language runtimes that can't manage the
scheduling for you while retaining the code context, has certain inevitable
results. You can (and should!) delay the inevitable, but it's still
inevitable.

At the _very least_ , I would suggest that if you going to consider using
Node.js you should be aware of the fact that it's not a blindingly new thing,
it's a relatively well-explored space being translated into a new language,
and you can get a good sense of the tradeoffs from the many previous
explorations of this space. There are still places where it may be the right
choice; as I said in that other message, I have chosen event-based coding in
another context because it was still the right choice. But I knew the
tradeoffs going in, and took steps to mitigate them, rather than being
blindsided by them.

~~~
MrMan
what do you think of that erlang version of the V8 interpreter I posted about
higher up? I do find the idea of using the erlang VM where it can do a lot of
good to be very attractive. While I would probably prefer python running on
Beam to Javascript, JS is very "lightweight" if you take my meaning a certain
way, and quite ubiquituous even compared to Python. It would also seem to
dissolve your specific complaints posted here, would it not?

~~~
jerf
I use this architecture myself where there's an Erlang thing sitting in the
center, dispatching relatively heavyweight jobs to Perl daemons waiting for
them, and it does work. That isolates all the "eventish" stuff in Erlang, and
turns the Perl daemons into, well, basically webservers, in the sense that
they are just serving stateless RPC answers synchronously. This definitely
avoids the complexity explosion.

You don't _need_ a project like Beam.js to do that, but having someone else
having already written the utility code can certainly be useful. Nothing like
that existed for Perl but it hasn't been hard to do what I needed.

------
hasenj
I prefer coffee-script. It also works in the browser.

<http://jashkenas.github.com/coffee-script/>

~~~
raganwald
The good news for fogus is that everyone who prefers CoffeeScript validates
the idea that an alternative syntax is enough of a win to be worth the
adoption headaches.

~~~
hasenj
It's not just syntax, but some semantics too.

Last expression in a function is returned. This includes assignment statements
which are in fact expressions.

    
    
      foo = () ->
        a = bar()
        z = () ->
          if a
            b = fu()
          else
            b = kar()
            

Here, foo returns the function z, and z returns either fu() or kar() while
assigning the value to b

One could argue this is just syntax but I think this way beyond the kind of
thing that comes to mind when somebody thinks of "syntactic sugar".

~~~
Homunculiheaded
Despite all of the weirdness of JavaScript, the lack of implicit return is
it's biggest design flaw imho. The functional/scheme-like virtues of JS are
well touted, but this small missing feature means implementing them always
requires the slight but constant overhead of ending every expression with
'return', which then means that programming in a way which should be natural
to javascript, isn't.

------
KeithMajhor
"My problem with Javascript has always been that expertise is defined more in
terms of understanding its faults rather than its features."

That's mostly just true for browsers. Javascript itself has very few faults.

My biggest annoyances with the language are: Lack of lexical scope, no
trailing commas and semicolon usage that differs from C.

I could complain all day about my annoyances with browsers (or just IE).

~~~
pygy_
Except that Javascript has lexical scope. Use the _var_ keyword to define
local variables.

    
    
        foo = function(){
            var bar=0
            return function(){
                bar=bar+1
                return bar
            }
        }
        baz=foo()
    
        baz() // => 1
        baz() // => 2
        baz() // => 3
        bar;  // => ERROR: bar is not defined

~~~
udp
They're "hoisted" and only local to the function, though. I'd (personally)
prefer it if it worked like C, and a variable was defined from the "var"
statement until the next closing brace. Then you could have a variable local
to one branch of an if statement, etc, without faking scopes by abusing
closures (eg _(function() { })();_ ).

And nested loops that both use "i" would work.

~~~
sedachv
"I'd (personally) prefer it if it worked like C, and a variable was defined
from the "var" statement until the next closing brace."

It does work like C. The scoping you're talking about was introduced in C99.

------
joelangeway
My greatest hope is that the makers of node.js will continue to abstain from
language changes. Some inconvenient syntax is a small price to pay for the
confidence that node.js isn't going to get turned into another regurgitation
of Java meets Perl by hordes of perfectly well meaning but unsatisfiable
programmers who want everything to work like the things they know. I don't
mean to insult the makers or users of other languages, just to highlight the
distinction of Javascript.

------
Fester
Fix the language, then fix event processing approach, then spend 10 yeard
maturing in the highly concurrent environments and end up being Erlang. w00t.

------
MrMan
Take a look at this, I am sure it has been posted on HN before:
<http://beamjs.org/>

This allows you to trade off all the cool speed of V8, but running node.js
singlethreaded, for running on an alpha port of V8 for the Beam VM. If you
want to sidestep the problems with Node.js, but keep the good parts, this
might be a way forward. Additionally, JS on the Beam VM can seamlessly
interact with any other Erlang code, so you get all kinds of other benefits
that are erlangy.

------
moomin
Don't get me wrong, this could end up being the best thing since sliced bread,
but the advantage of closures is that a higher-order approach can work
wonders. Just take a look at async.js.

For me, more interesting than a pure assault on callbacks would be to see if
you could handle more asynchronous scenarios, using async.js as a baseline.

e.g. callback waterfall, callback when all children are finished, callback
when any children are finished

~~~
randylahey
I wish this was rated higher. I don't understand the fuss about "spaghetti
code". Do all those people write spaghetti code in other languages? Because I
see that not as a language failing but as sloppy programming.

What's so hard about this to get a sequential execution of functions/blocks,
error'ing out on the first error:

    
    
        async.waterfall(
          [ function (callback) {
              // do thing 1
              callback();
            }
          , function (callback) {
              // do thing 2
              callback();
            }
          , function (callback) {
              // do thing 3
              callback();
            }
          ]
          , function (error) {
              if (error) {
                // ohnoes errors
              }
    
              // all done!
            }
          );

------
DTrejo
Not sure why he uses this as a code sample, as it's also not how someone would
write code (though I suppose he is entitled to his style).

 _The original from the article_

    
    
      function do_request(req) {
        return long_io_operation(
        req, 
        callback=function(results) {
          return create_something_from(results);
        });
      }
    

_How it might be written if you saw it in a codebase_

    
    
      function do_request(req, callback) {
        long_io_operation(req, function(err, results) {
          callback(err, create_something_from(results));
        });
      }
    

It seems like the article is not finished, so I can understand that there
might be questionable sections. Also you'll note that he forgot the `error,
results` argument pattern for callbacks, making me think that he is not
terribly familiar with node.

------
ericmoritz
all I'm asking for with Javascript is a shorter function keyword. Let me have

dosomethingasync(f() { });

With a language so dependent on callbacks, anonymous function are so verbose.

~~~
Cushman
Try CoffeeScript.

    
    
      dosomethingasync ->
          #etc

------
jasongullickson
I'm all for a new version of Javascript that eliminates the junk and keeps
just the "Good Parts", but I'm averse to anything that serves to abstract away
the bad parts by building a subset of functionality on top of the existing
version javascript for a niche application (server framework in this case,
other cases include cappuccino for UI, coffeescript for...everything? etc.)

 _The Javascript that can be used only via add-ons is not the eternal
Javascript..._

------
kreek
How about Node.as? Flash doesn't get much love these days but I've always
thought ActionScript 3 would make a great server side language. It's more like
other OOP languages, has an event model like JavaScript (sync or async), and
doesn't have many of JS's idiosyncrasies.

Edit: <http://haxe.org/> is based on AS3

~~~
jpravetz
I agree. I had to go back from AS3 to AS2 for a project and it felt like a
step backwards, and AS2 is more like Javascript. Adobe has also open sourced
the AS3 runtime. But of course the practicality is that we have Javascript in
browsers, and there's a big get-the-job-done benefit to using a common
language.

------
balakk
Is it ML week on HN? Sounds like everybody has got ML envy now..

