Announcing Ozma: extending Scala with Oz concurrency

I am happy to announce the release of Ozma, a conservative extension to Scala that adds Oz concurrency. Ozma was developed as a master's thesis by Sébastien Doeraene under my supervision (see the implementation and the master's thesis).

Oz is a multi-paradigm language that has strong support for concurrent and distributed programming. It compiles to its own virtual machine (called Mozart) that supports dataflow synchronization and lightweight threads.

Scala is a functional and object-oriented language with implementations for the JVM and .Net. It is completely interoperable with Java.

Ozma is an attempt at making the concurrency concepts of Oz available to a larger public. Ozma implements the full Scala specification and runs on the Mozart VM. It can therefore be seen as a new implementation of Scala. Ozma extends Scala with dataflow variables (allowing tail-recursive list functions), declarative (deterministic) concurrency, lazy declarative concurrency, and message-passing concurrency based on ports. Almost all the concurrency examples of CTM can be translated easily to Ozma. We can say that Ozma lifts the duality of Scala, namely the combination of functional and object styles, to concurrent programming.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Impressive

I'm impressed by the scope of the project. Scala is not a simple language, and diving into its compiler internals to translate it towards Oz AST must have been a definitely not easy task.

I have had a quick look at the report with interest. A few remarks below.

I'm surprised by the deliberately "political" taste of the introduction; relevant languages and projects -- I was in particular looking for the Alice ML reference -- are mentioned, only to say that they "did not get traction among the developer community". While this is true, I'm not sure why this presentation was chosen, and what it is trying to say. Does it mean that Ozma was thought as "get successful" reinvention of Oz? I would be quite surprised if that turned out to be the case.

Of course, the next big question -- in particular if you try to get in to that "get successful" mindset -- is performance-related. How fast can the Oz VM be compared to the implementation work juggernaut that is the JVM? The report only say that they expect the performance of the current iteration to be terrible, which was expected for a short-time project, but how good could it get? The report also reports impedance mismatches between Scala and Oz constructs, for example on functions; are those solvable? Do they really affect performances?
Performance consideration would also come in play in the design choice between a language where all variables are dataflow variables, à la Oz, or a language with a dedicated type of dataflow values. I would expect the dedicated type in a general language to be slower than the optimized representation of the Mozart VM, but then you don't pay the overhead for "standard" variables that don't use the dataflow constructs.

It could also be argued that making the difference between the non-dataflow and dataflow parts help readability and understanding. Relatedly, I find it a bit confusing, for example, to have devised "lazy" variants of standard Scala list datatype, without using a different datatypes. In Ozma (as in Haskell), when you see a list, you don't know if it's to be used as a finite strict list or a potentially infinite lazy stream. In practice the interface and reasoning are different, so it would make sense to use different data types.

I've been very interested in the discussion of the @tailcall argument. Just saying "we notice consing and optimize it to preserve tail calls" looks like a ugly ad-hoc solution to a more general problem -- though it is later explained that Oz really optimize all record constructions; I enjoyed reading CTM a few years ago but didn't recall this specific thing -- but the @tailcall annotation handling and discussion is interesting. In particular, it reminded me of the discussion in the ML community on value recursion; cyclic constructors (let rec li = 1::li) are meaningful. More generally, as in your @tailcall case, this is about whether we "force" the evaluation of the recursively defined identifier or not. OCaml has chosen a restrictive static classification (see the documentation), but other choices have been proposed, such as fully dynamic (allow everything but fail at runtime if the yet-undefined identifier is forced). I'm curious of how related are the two problems of recursive definition and tail-call preservation.

Finally, the fact that some of the Scala compiler passes (lambdalift) do not respect annotations in a satisfying way is mentioned. Is it an Ozma-specific problem, or could the change described in the thesis be contributed upstream to improve the Scala compilers? Devising a flexible compiler with modular mechanisms to pass information across phases is a difficult problem.

Thank you for your feedback.

Thank you for your feedback. I will try to answer them adequately.
(just to make it clear: I am Sébastien Doeraene, designer of Ozma).

The introduction is indeed quite "political", as you mentioned. The main issue is: how to make dataflow variables be well known and accepted in mainstream communities. We do not particularly want Ozma to "get successful". What we really want is dataflow variables to get successful (and with them declarative concurrency, lazy execution and the like). Ozma itself might not be the solution, but we would like, and expect it to at least make mainstream communities question themselves about that.

Regarding performance. The main source of performance issues in Ozma are currently related to the fact that we "blindly" translated in Oz the Java-like classes generated by the Scala compiler. Now, many Scala constructs are refactored a lot by the compiler to fit in Java concepts, but they could be given as is to the Oz compiler, which has built-in support for them. The most obvious examples are anonymous functions, and all the work done by the 'lambdalift' phase.
The Mozart runtime engine is already optimized for these kinds of constructs. Considering the heavy use of anonymous functions in Scala, we might even get performance gains in Ozma if optimized appropriately, in some cases.

About performance issues regarding dataflow variables being everywhere, this is indeed an issue that still needs to be considered. But there is a lot we can learn from the FlowJava experience.

The infinite list mechanism, we transposed it directly from Oz to Ozma. I agree this is arguable in general.

I'm glad the @tailcall thing got your interest. It's one of the few design issues I really had to motivate in front of Oz people (and in particular Mr Van Roy, of course). I will look into the other approaches (didn't know about them :-s).

The lambdalift problem is, according to me, more general than its application to Ozma. But I understand the choices of the designers of the Scala compiler not to replicate annotations everywhere. It's not clear whether a particular should be replicated or not. Maybe we need some kind of additional mechanism to decide that.
Note that, in general, I was very impressed by the modularity of the Scala compiler. Without that I would probably not have been able to support so much of Scala specifications.