Peter Van Roy wrote: > David Hopwood wrote: > >>> In the case of threads, the original version of Oz, Oz 1, created >>> threads implicitly. >>> After some time we saw that this was the wrong decision. For example, >>> it makes reasoning about termination much harder. Again and again, we >>> learned the lesson that making things explicit is the best solution: >>> state, threads, laziness, search. >> >> Perhaps this conclusion should be extended to explicit waiting on >> dataflow variables ;-) > > I don't think so. Just the opposite: [explicitly waiting on dataflow > variables is actually the more complicated thing].
The kernel language and its semantics are not significantly more or less complicated. Whether programming in the full language with explicit waits is more complicated is a matter of what you're used to. Yes, you have to write slightly more code with explicit waits. But that code is straightforward, and it makes turn boundaries explicit. This is just like making threads or other features explicit: you have to write slightly more code, but that code is easier to reason about. How is it easier to reason about, you may ask? Most importantly, it is easier to reason about the atomicity, consistency and isolation of state updates. Immediate calls that are performed in the same "turn" are guaranteed not to be interleaved with calls from other vats. That is, the side effects of a turn form a kind of transaction -- but one that is lightweight enough to be used routinely. In terms of ACID properties (http://en.wikipedia.org/wiki/ACID), strictly speaking these lightweight transactions only *guarantee* the Isolation property (in its strongest form: serializable isolation). Atomicity and Consistency can't be automatically guaranteed at this level, at least not without much greater overhead and complexity. However isolation is a prerequisite for writing code that manually ensures atomicity and consistency. Durability is dealt with by other mechanisms in E. (Although this behaviour could be partially simulated in other message passing models by combining each sequence of methods that needs to be isolated into a single method, that simulation is inadequate because it requires changing the target object by adding boilerplate code, and because it doesn't work for groups of objects.) Note that in cases where a task written in E needs the results of several promises, the implementation of the task will not necessarily leave it until the last moment when a given promise is used to wait for its value. In general, it will split the task over several turns, where each turn that needs a given set of variables is isolated from the point of view of other vats. Because the waits are explicit, the programmer is encouraged to think about where the boundaries between turns should be, i.e. what intermediate states should be observable. It is also very easy to reason about when programs can wait, which is important in interactive, distributed, and real-time applications (although E is not suitable as a hard real-time language as it stands). I am not arguing that E gets this absolutely right, BTW, at least not in its current implementation. It could do with better support to help the programmer to keep track of which references are resolved, which are near (i.e. in the same vat), etc. E was intended to support soft typing, which could provide this information, but the compile-time part of this is not yet implemented. [to be continued...] -- David Hopwood <[EMAIL PROTECTED]> _________________________________________________________________________________ mozart-users mailing list [email protected] http://www.mozart-oz.org/mailman/listinfo/mozart-users
