Hi James,
interesting read. Reading your post I got a bit confused and therefore looked up some articles on the Internet to understand what yield in Scala really does. I must admit that I had no propper understanding of what “yield” is for in Scala. I thought it had something to do with the current thread voluntarily giving up the processor for some other thread or it means that some thread is spawned. I thought this had something to do with the Futures created (Future[List[Order]]). I was a bit too careless there, I guess, and too quick in making a post. Anyway, now I understand why collect has disappeared in stdlib and has been replaced with map ;-).
In that case this statement
val orderHistory: Future[List[Order]] = for {
id <- CustomerLookupActor.ask(customerName).mapTo[Int]
details <- CustomerDetailsActor.ask(id).mapTo[CustomerDetails]
history = details.orderHistory
} yield history
is only about looping and has nothing to do with actors. Oops … The interesting part concerning actors is the Future[List[Order]] thing. But how to implement a Future is a library issue, not a language issue. The above example is probably not a good sample for the power of yield (see this article). A simple Smalltalk/Groovy-style collect iteration would do the same in that specific case.
Also, excessive looping is a hint for broken design (some classes or methods missing? lack of information hiding?). At least in OOP. Maybe not in functional programming where this yield thing might have its place. To me, OOP, functional programming and Erlang all thrown together into one language is just three languages in one. But it does not create a meaningful fusion of those things to form a new coherent construct. To achieve this the Scala people would have had to think, f.ex., how Erlang can be combined with OOP and then bring the combination to Scala rather than just adding Erlang to it. Instead, to make it worse, they even added case classes to it, which you happily don’t need in OOP. That was when I lost my interest in Scala. Okay, I’m starting to make a digression …
Another issue is that exception handling in asynchronous programming is really hard, see “<a href=”http://www.lirmm.fr/~dony/postscript/exc-inbook06.pdf“>Exception Handling and Asynchronous Active Objects” (see the section about Guards). IMHO Scala actors and akka don’t do much about it. Futures, supervision, fault-tolerance don’t solve this. It’s just something they’ve taken from Erlang. Those things are useful, but not sufficient. I was talking to them on the akka mailing list and one of the guys from Typesafe seemed to be interested. Let’s see. I have my own ideas from earlier when working on asynchronous control systems, but I’m a regular developer and not an exceptional one like you guys who have freedom to play with things at work they are interested in. I have to develop some software for some company and only can play with those things in my spare time and that is never enough for something really serious.
I think a better approach than using Erlang’s receive { … } clause as in Scala and other languages is to add closures to queues as with Grand Central Dispatch or HawtDispach. Erlang’s receive thing, IMHO, is some solution you have to stick to if you are forced to program with global functions and don’t have classes and instances. Adding closures to a queue that is served by its own thread gets around having to define case switches in the receive clause as in http://www.scala-lang.org/node/242 I think that would be something cool to work on :-).
Regards, Oliver