March 25, 2014

Make Install: Polycode

I somehow stumbled on Polycode, which is an interesting "free open-source framework for creating crossplatform games and interactive applications". It reminds me a bit of Processing, except that you use C++ or Lua for creating applications.

In addition to supporting 2D and 3D applications, it features a large selection of asset loaders (including Blender, of course) and has a Unity-like IDE. Runs on all major platforms, though there are no ready-to-download executables yet. You'll have to build everything from source to get started.

As an added bonus, there is a blog linked to the polycode. Always nice to see developers writing about their pet project.

March 15, 2014

Minimalist Dataflow Engine

I'm really enjoying these minimalist literate programming exercises, so here is another: a minimalist dataflow engine named "dfntly". It is very loosely inspired by the excellent Knockout library, but obviously has much fewer features. I would like to add some support for observable arrays, for example, and for asynchronous calculations where the dataflow engine only calculates further when the reply comes in. But that's something for another day.

In the meantime, if you feel like it, give it a go!

March 10, 2014

On "The Next 700 Asychronous Programming Models"

I was watching this talk by Philipp Haller on InfoQ on "how to make Rx programming more natural and intuitive by generalizing Scala's Async". The cliffnotes are this: unify the two by implementing async through observables. Clever.

Now, while the result was interersting I got a bit "stuck" thinking on this example from the presentation:

val futureDOY: Future[Response] =
  WS.url("http://api.day-of-year/today").get
val futureDaysLeft: Future[Response] =
  WS.url("http://api.days-left/today").get

val respFut = async {
  val dayOfYear = await(futureDOY).body
  val daysLeft  = await(futureDaysLeft).body
  Ok("" + dayOfYear + ": " + daysLeft + " days left!")
}

What it's trying to do is retrieve data from two remote services and compose the results in some way (don't worry about what it's really trying to achieve; it's one of those hypothetical examples which academics are really good at; I know, I used to be one). Now, as you may have noticed the services are consumed in an asynchronous way. That's where the need for futures and explicit waits for their results comes in.

Having been playing a bit with futures and their composition for the minimalist asynchronous process virtual machine I understand the mind bending it can take to get this right in more realistic examples. As a programmer you constantly have to be aware of what methods return results which are immediately available (i.e. are synchronous) and which ones are not. Because if you get it wrong the results will be unexpected and probably quite annoying to debug.

So here comes my question: rather than trying to come up with lots of creative ways of composing asynchronous behaviours and avoiding callback hell, why not stick to the principle of least surprise and make all asynchronous calls act as synchronous ones by default ? What is really stopping the above code from being as simple as:

val dayOfYear = WS.url("http://api.day-of-year/today").get.body
val daysLeft  = WS.url("http://api.days-left/today").body
val respFut = Ok("" + dayOfYear + ": " + daysLeft + " days left!")

A programmer's default mindset, I would argue, is that code is synchronous. By making that the default the obvious solution becomes a correct one.

Asynchronous execution, if wanted, can still be supported by explicitly requesting it. So another way to write the example could be:

val futureDOY: Future[Response] =
  async { WS.url("http://api.day-of-year/today").get }
val futureDaysLeft: Future[Response] =
  async { WS.url("http://api.days-left/today").get }

val respFut = async {
  val dayOfYear = futureDOY.body
  val daysLeft  = futureDaysLeft.body
  Ok("" + dayOfYear + ": " + daysLeft + " days left!")
}

While not as concise as the earlier rewrite at least it removes all doubt about which parts of the code don't want to wait for specific results.

Anyway, just wanted to get this off my mind. If you like, or think I'm just blowing smoke, let me know.