Hacker Newsnew | comments | show | ask | jobs | submit login

I think the author is missing the obvious and natural solution: let the programmer write code in a completely synchronous (blocking) style, but have the programming language execute it an an asynchronous and concurrent fashion. Something like that:

  # this appears very synchronous
  function getPhoto(tag) {
      var photoList  = syncGet(requestTag(tag));
      var photoSizes = syncGet(requestOneFrom(photoList));
      return sizesToPhoto(photoSizes);
  }

  # Two getPhoto() "processes" are spawned. After this,
  # the language multiplexes between them via the (single) event loop,
  # in a single OS thread.
  job1 = spawn getPhoto('tokyo');
  job2 = spawn getPhoto('tokyo');

  # Wait for both of them to finish. This too happens in an asynchronous
  # fashion, i.e. calling job1.join() does not prevent the two jobs from
  # running. In effect at this point we have three "processes" running
  # (the main process doing the joins, the job1 process and the job2 process).
  photo1 = job1.join();
  photo2 = job2.join();
  drawOnScreen(photo1);
  drawOnScreen(photo2);
Yes, I know this may be very hard to implement in Javascript/Node, because it fundamentally changes the way the JS engine needs to work.

NOTE: It seems this approach is not new; "green theads" seems to be the right term, and there seem to be a lot of Python-based implementations. Go's goroutines also appear similar (but you can have them run truly in parallel).

BUT note a crucial difference from the "green threads" approach - in my suggested design, there would be no real scheduling. If you perform sequence of operations and they are all guaranteed not to block, this sequence is automatically atomic, and cannot be interrupted by another "process".

I should also mention this programming language I'm developing, called NCD [1], which employs the same idea. See the in-browser demo [2], click on the Spawn example.

Note that NCD implements a unique extension of imperative programming. Statements in general persist even after they have "returned", and they get the chance to do stuff when they are about to be "deinitialized" (see what happens when you click "Request termination" in the Spawn example). Plus, any statement can trigger "backtracking" to its point within the process, causing automatic deinitialization of any statements that follow (try Count example).

Also, IMO promises [3] are just a hack around the fact that the language is not inherently asynchronous. Seriously, who would prefer:

  doFoo()
      .then(function (foo) {
          return doBar(foo);
      })
      .then(function (bar) {
          return doBaz(bar);
      })
      .then(function(baz) {
          console.log(baz);
      });
Over this?

  function myWork () {
      foo = doFoo();
      bar = doBar(foo);
      baz = doBaz(bar);
      console.log(baz);
  }
  spawn myWork();
[1] http://code.google.com/p/badvpn/wiki/NCD [2] http://badvpn.googlecode.com/svn/wiki/emncd.html [3] https://gist.github.com/3889970



Green threads are indeed very useful, and probably the right way to go. In Javascript, see Tamejs: http://tamejs.org/

NCD looks interesting, in particular the backtracking feature. But I'm a bit concerned by your choice of developing a new language from scratch, with a very awkward syntax (at least at first sight). Why not extend an existing language?

See CPC for instance, which extends the C language with a spawn primitive (disclaimer - this is my PhD thesis project): http://www.pps.univ-paris-diderot.fr/%7Ekerneis/software/cpc... and http://www.pps.univ-paris-diderot.fr/%7Ekerneis/research/ for more details.

-----


Yes, Tamejs and CPC indeed do exactly what I had in mind. CPC is particularly amazing for doing this to C.

Considering NCD: you might have noticed that NCD was never meant to be a general-purpose language, but rather a simple scripting language for controlling other programs and OS configuration. My thinking was that extending a language with the features that define NCD (asynchronous execution, backtracking and extended statement lifetime) would essentially require a complete rewrite of a language implementation. However after seeing tamejs and your CPC I'm not so sure anymore :)

P.S. Check out the Read File example I just added to the NCD demo page; it shows how backtracking can be used to handle errors elegantly.

-----




Applications are open for YC Winter 2016

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

Search: