News for hackers. Stuff that matters.
Re:JavaScript's world domination by chubot on Tuesday March 24, 2015 @05:13PM (#9259540)
Not just first class functions -- anonymous functions, and closures.

Python has first class functions, but not anonymous functions, since lambdas aren't full functions.

And Python doesn't have closures, because you have to use "global" or "nonlocal" (in Python 3) to assign a a variable in an enclosing scope.

These features let you write concurrent state machines in JS without explicit state -- you basically use the stack as state.

Python was pretty early in terms of event loop programming for interpreted languages -- asyncore in the stdlib, and Twisted. But I agree that the node.js style is nicer than asyncore, Twisted, or Tornado. I prefer coroutines over state machines, but if you're going to write state machines, than doing it with anonymous closures is nicer than doing it "manually" with classes and so forth.

Tcl was even earlier, but Tcl is pretty foreign to most people, and was more of an embedded language than a scripting language. Pretty sure Tcl has full anonymous closures, but it is a bizarre language in some other ways.

I haven't seen the event loop style in Perl but I think you can do it. If someone has an example I'd like to see it. To me, Perl only barely qualified as a real programming language because you can't even name your function params? At least when I used it, which was over 10 years ago.

Re:JavaScript's world domination by barosl on Tuesday March 24, 2015 @06:55PM (#9260109)
> I prefer coroutines over state machines

And that's why Python supports `asyncio` (not to be confused with `asyncore` which is obsolete). So I prefer:

  sock = yield from connect('localhost', 7942)
  msg = yield from read_message(sock)
  print(msg)
to this callback hell:

  connect('localhost', 7942, function(sock) {
      read_message(sock, function(msg)) {
          console.log(msg);
      });
  });
And they're completely equivalent. Why would someone actually like the latter, except you're forced to use it because of the prevalence of JavaScript?

`asyncio` is not only easier to use than the traditional "manual" state machines with classes, but also much faster than something like `Twisted`. In my crappy local benchmark[1], it easily beat `Twisted` in a considerable margin. That may be because of the flaws in my test code, but still their performance is on par. I see no points in relying on callback hell, at least in Python, except the lack of the libraries that support asyncio, which makes me a little bit sad.

[1] https://github.com/barosl/ws-bench

Re:JavaScript's world domination by chubot on Tuesday March 24, 2015 @06:57PM (#9260117)
Yeah but node.js predates asyncio by about 5 years. Python was early to the game with asyncore and Twisted (circa early 2000's), but the async I/O support stagnated and left a big hole for node.js.

Part of the reason for stagnation was because you really need new language features -- i.e. yield/send, yield from, etc. JavaScript already had the necessary language features for its concurrency model.

Re:JavaScript's world domination by barosl on Tuesday March 24, 2015 @07:04PM (#9260164)
That's a good point. I also think `asyncio` was way too late in the game. I just wanted to mention the feature that was missed from your comment, which I think is not fair to Python.
Re:JavaScript's world domination by jsprogrammer on Tuesday March 24, 2015 @09:46PM (#9260799)
You can do that with current ES transpilers:

    async read(connect, readMessage, print) {
        const sock = await connect('localhost', 7942),
              msg = await readMessage(sock);
        print(msg);
    }
Re:JavaScript's world domination by omphalos on Wednesday March 25, 2015 @04:34AM (#9261788)
You can do it now without a transpiler if you set harmony flags in Chrome/Node and use yield+co. (And just use a transpiler for deployment.)
Re:JavaScript's world domination by raksoras on Tuesday March 24, 2015 @08:32PM (#9260555)
Coroutines are much better suited to event driven, non blocking IO code. Sorry for the shameless plug but I recently released my hobby project that uses Lua coroutines for nonblocking HTTP server: https://github.com/raksoras/luaw

Lua was quite pleasant to work with in this context!

Re:JavaScript's world domination by olegp on Wednesday March 25, 2015 @12:39AM (#9261325)
Agreed, but Node has had co-routines in the form of the node-fibers package since almost the very beginning.
Re:JavaScript's world domination by findjashua on Tuesday March 24, 2015 @07:34PM (#9260311)
async/await is the biggest reason I'm looking forward to ES7.
Re:JavaScript's world domination by jsprogrammer on Tuesday March 24, 2015 @09:43PM (#9260790)
You can use it now with Traceur or Babel. Traceur recently (~1 month ago) got support for async generators (yield + await in same function).
Re:JavaScript's world domination by timepiece on Tuesday March 24, 2015 @07:02PM (#9260148)
Can't you use promises/deferreds instead?
Re:JavaScript's world domination by ufo on Tuesday March 24, 2015 @07:16PM (#9260230)
One thing yield/await does is that if plays nice with existing control-flow mechanisms in the language. You can put them inside a for loop, if statement, try-catch block, etc. With promises all of those have to be reimplemented in a library and all your code needs to be converted to the "promisified" version of things.

The different syntax also prevents you from creating functions that can be reused by both sync and async code.

The big thing promises and other callback-based control flow libraries do is that they fix exception handling in async code (its a PITA to add error handlers in every callback when writing async code by hand). They also let you avoid some of the awkward "pyramid of doom" nesting but thats not really killer feature because you can also achieve that by using tons of named functions.

Re:JavaScript's world domination by tracker1 on Wednesday March 25, 2015 @03:21AM (#9261646)
async/await are coming with ES7 and available today with BabelJS and other transpilers. Though not part of core, they rely on thenables/promises, which handle the reject/resolve which get composed with generators.

The required bits are in place... alternatively you can use co/koa which uses generators along with yeilding promises to act in a similar fashion.. it does work pretty well, and will only get better.

Re:JavaScript's world domination by barosl on Tuesday March 24, 2015 @07:09PM (#9260196)
I do think promise and deferred are huge improvements to ergonomics, but still... I cannot completely love the code bloat (which is much smaller and easier to reason about than callback hell, of course) that is caused by those libraries. I much prefer Haskell's monadic interface or Python's `yield from`. But that may be my personal preference.
Re:JavaScript's world domination by timepiece on Tuesday March 24, 2015 @07:13PM (#9260217)
Grownups in charge of the lang are listening and they're doing their best to incorporate these features (async/yield) in the language as soon as possible.

Don't despair the future is bright :)

Re:JavaScript's world domination by pdpi on Tuesday March 24, 2015 @05:40PM (#9259677)
On the other end of the spectrum, Ruby blocks (and all the attached machinery) feel to me like a much nicer abstraction to work with. Go's goroutines and channels show giving a language purpose-built concurrency primitives is a really nice model (I expect Erlang would be another good example of the same, but never tried it), and the monadic approach in Haskell makes it so that you could almost directly translate node.js code and end up with something far more readable.
Re:JavaScript's world domination by ufo on Tuesday March 24, 2015 @06:30PM (#9259964)
TBH Python is a bit of an exception there. Most languages with first-class functions (specially more modern ones) will also come with anonymous functions that aren't intentionally crippled (like Python's lambda is) and will have more traditional lexical scoping instead of local-by-default.
Re:JavaScript's world domination by chubot on Tuesday March 24, 2015 @06:53PM (#9260101)
Which ones?

Python isn't an exception among languages that people in industry actually use.

For "production grade" server software, which is driving the newfound interest in concurrency, the following languages cover 99% of code written in the last 20 years: C/C++/Java/PHP/Perl/Python/Ruby and the Microsoft Stack (C#, VB).

None of them have anonymous closures. (C# might, but it's also newer, and it's not the the prevailing style of concurrency in any case.)

This is basically JavaScript's Scheme heritage showing through. Anonymous closures are old hat for people who went through a CS program teaching Lisp, but they're not by any means standard in industry.

One of the main reasons that none of the languages needed this feature is because the predominant paradigm for concurrency for the last 2 decades was threading, not state machines and callbacks.

Re:JavaScript's world domination by Sanddancer on Tuesday March 24, 2015 @09:04PM (#9260654)
C#'s had closures and anonymous functions for almost a decade, Java's got them properly now with Java 8, but you could always hack them with anonymous inner classes. C++ got them in C++11, etc. Hell, even in C, you could hack something resembling a closure with a struct and a function pointer.
Re:JavaScript's world domination by nawariata on Tuesday March 24, 2015 @07:18PM (#9260237)
PHP has closures.
Re:JavaScript's world domination by TazeTSchnitzel on Tuesday March 24, 2015 @08:51PM (#9260610)
Pseudo-closures. They capture variables by value, though you can use PHP's referencing mechanism to have something sort of closure-like.
Re:JavaScript's world domination by afjgasdfjlasdf on Tuesday March 24, 2015 @08:23PM (#9260518)
There is no such thing as an "anonymous closure". There are only anonymous functions which may or may not create a closure. Early LISPs either had no way of creating closures, or did so through some sort of function or other mechanism. It wasn't until Scheme came around that lexical closures really became a thing in Lisp world.

Perl and PHP both have closures. In fact, Perl is closer to Scheme/Lisp than most languages (at least Perl doesn't screw up scoping like JavaScript, replace first-class functions with second-class-bastardizations like Ruby, or do whatever Python thinks it's doing with lambda... ugh)

Re:JavaScript's world domination by chubot on Wednesday March 25, 2015 @12:48AM (#9261352)

    #!/usr/bin/node

    function main() {
      var a = 1;
      console.log(a);
    
      // named closure
      function foo() {
        a = a + 1;
      }
    
      foo();
      console.log(a);
    
      // anonymous closure
      (function() {
        a = a + 1;
      })();
    
      console.log(a);
    }
    main();
Re:JavaScript's world domination by kaoD on Wednesday March 25, 2015 @07:40AM (#9262261)
I'll emphasize GPs words:

> There is no such thing as an "anonymous closure". There are only anonymous functions which may or may not create a closure.

Which is exactly what you did: calling an anonymous function which happens to create a closure over variable `a`.