Play's documentation on iteratees is definitely dense. One of the contributors has posted a far better explanation (compared to the docs, not this post) on his blog:
I have an weekend project that uses Play's iteratees and enumerators quite well (IMO). They act as plumbing between client events (interacting with an embedded map), fetching and writing data to Mongo and interacting with the FlightAware API. I used server-sent events instead of WebSockets.
I think the OP is correct in that Play's iteratees/enumerators are fantastic but too low-level for most applications. Play (or a third-party) need to provide a high-level abstraction so that developers can ramp up as quickly as with socket.io.
Perhaps you can clear up my confusion with the article. It appears to me that Play is basically implementing Rx, except with a pointless new set of terminology. The Node examples could have all been structured almost identically to the Play examples if they used rx. What advantages or extra functionality is enabled by enumerator/enumeratee/iteratee that you can't get with observable?
Play didn't invent the iteratee concept, Oleg Kiselyov did (http://okmij.org/ftp/Streams.html). I asked myself the same question, as I'm doing the reactive programming course on Coursera, where Rx was the topic of the last couple weeks. I came to the conclusion that Rx focuses on side-effects while iteratees concentrate on iterative calculations. Iteratees calculate a result while Rx-observers just perform side-effects.
Maybe someone else can further elaborate on this topic.
Quoting Roper: The complexity of iteratees comes because they handle many different things at once - async io, backpressure, producing results, composition on multiple different axes. Most other APIs that they get compared to only handle one or max two of these, so the complexity of those APIs is not in what they do, but what they don't do that you have to implement yourself.
As someone who has used both, I have to give this battle to Node.js and Socket.io. The ease of use because of the common client/server code almost blurs the line between the client and server and makes it almost a pleasure to use. Whereas in Play/Scala, there isn't a libary I can use for both the client and server, thus I either have to write my own client library (or use one) and then write my server code. From a maintainability standpoint, Node, in this particular use case, just demolishes Scala/Play.
Your main point appears to be sharing code on the client and server side. Scala.js has reached 0.1 and is quite decent [1]. Personally, the only code I find worth sharing is validation code and template rendering code. As for "maintainability", I find it is much lower in node.js and JS projects in general. Each has its own structure and is scary to refactor (unless you're a TypeScripter or something). I don't believe it's fair to use those two points to say it "demolishes" Scala/Play. Also, some webapps do real work per request (not just routing IO), and even though it is very quick (i.e. not worth farming out to a resque-like job engine or a web-worker in node), the fact that it blocks the node process scares me as well.
I think it's a bit over the top to compare Scala to JavaScript and node.js.
If you're comparing the two you have way more flexibility than you should because these are two widely divergent tools with different implications reaching beyond "easier" or "faster." I don't think people ought to even consider scala if they're considering "easy" as being a significant factor.
Scala enjoys type safety and compilation and a vast and deep sophisticated feature set, not the very least of which is inherited from the proven and storied java libraries. Node.js is a mess of shit heaped on the turd that is script-kiddy npm-land covered with int-less and unicode unsafe JavaScript.
This is such an odd argument. As a developer that likes to produce usable products, 'easy' is something I'm always looking for. Why not? Just because something is 'easy' doesn't mean it's inadequate. It all depends on what you're building.
Also, your misguided rant against node and npm rather hurts your credibility. Your argument was at least ok up until that point.
Pretty sure dependencies can come straight from a git url, bypassing npm. Put something on npm, and in your package.json you can depend on something straight up from github. npm will install and build that and it may break your stuff, it's a gamble. Given how dependencies nest into a massive web, you don't have to use many things before you end up with something that breaks you.
shrinkwrap just locks down a version of a dependency, if the dependency points to a git master branch, that's not locked down. shrinkwrap doesn't install any code. I think his point is valid, although also probably still very rare.
Similar to the Node + Socket.io example, here is a Spring 4 + SockJS example (the example is a trading application instead of chat, but the concepts underneath are pretty similar):
This has become my common stack along with Angular on the client side. It makes for some slick interactions when you can have the client acting just like an actor passing messages back and forth to the server. It might still be a different language ( JS and Scala ), but since I am using the same flow in both of them I have been able to adapt.
This is a great demonstration of how bad Play Iteratees are. One of the most impenetrable and frustrating API's I've ever used. Invariably I'd end up using the Concurrent._ imperative APIs to work around them.
I'm assuming that the Iteratee companion object uses implicits to get the client connection. I'd really prefer something more explicit like socket.io's approach.
That assumption is incorrect. Implicits are not used here (for that purpose anyways).
The client connection is handled by that "WebSocket.using[String]" handler. This is just a function that takes a function which takes a Request and returns an Iteratee and an Enumerator. In Play, this is known as an Action. Actions take Requests and return Results.
So the client connection is not bound using implicits, it's bound when that function is actually executed. This function (f) is invoked by the router when a request comes in for that controller action. This is done using HandlerInvoker: http://www.playframework.com/documentation/2.2.x/api/scala/i...
Now, my explanation is not the most eloquent nor is it really necessary to understand all of this, though it certainly helps.
http://mandubian.com/2012/08/27/understanding-play2-iteratee...
I have an weekend project that uses Play's iteratees and enumerators quite well (IMO). They act as plumbing between client events (interacting with an embedded map), fetching and writing data to Mongo and interacting with the FlightAware API. I used server-sent events instead of WebSockets.
I haven't touched the code in a while (and the API key in the repo doesn't work ;)) but I have a working prototype that tries to stay entirely async: https://github.com/ryantanner/flightsight/tree/master/app
I think the OP is correct in that Play's iteratees/enumerators are fantastic but too low-level for most applications. Play (or a third-party) need to provide a high-level abstraction so that developers can ramp up as quickly as with socket.io.