On 16. Apr2009, at 21:46 , Adrian Quark wrote:
>
> I'm one of the people working on Orc -- http://orc.csres.utexas.edu --
> and I came across Oni while looking at related work. First, I want to
> say that I think this is a great idea; the message of Orc is not that
> people should start writing their programs in the Orc language per se,
> but adapt the combinators to existing languages as much as possible.
I'm a big fan of Orc - in fact Oni grew out of an experiment in
implementing Orc for JavaScript a couple of years ago. I took the
'Implementation Outline for Orc' paper (http://orc.csres.utexas.edu/papers/OrcImpDraft.pdf
) as a starting point and soon after I had a parser/interpreter that
could execute some very basic Orc expressions.
At this point I became interested in how the compositional concurrency
ideas behind Orc could be retrofitted to exisiting languages and
whether this could be done in a more 'conventional' semantic style
whilst keeping (at lease some of) the expressiveness of Orc. I'm not
sure yet how successful it is by either of those metrics, but Oni is
the result of this ongoing excercise :-)
>
> I have a question about Oni's Alt, which is similar to Orc's where/
> pruning combinator. As far as I can tell, if you bind the value
> produced by Alt to a variable with Let, the body of the Let can't
> execute until the Alt produces a value. In other words, Oni doesn't
> have futures. Is this accurate? My experience with Orc has been that
> futures are a key part of the language's expressiveness.
Your observation that Oni doesn't implement futures is accurate. The
main reason is that I don't think adding futures in a naive way (e.g.
like in C++0x) would actually add expressiveness - but I'd be very
interested in finding out about scenarios where they do!
I have some longer term plans of making Oni mostly non-strict like
Haskell. I think this will really bring tangible improvements in
expressiveness, like e.g. being able to express a large class of
producer-consumer patterns in a structured way through the use of lazy
lists. If this pans out as planned (I'm still very hazy on the
details), futures will feature prominently behind the scenes, like in
Orc.
Regards,
Alex
>
> [...]
> The "parallel or" implementation in Orc is a good example of the use
> of these kind of futures. How would you encode this in Oni?
> http://orc.csres.utexas.edu/userguide/html/ch02s02.html#N10FBF
>
Parallel-Or can be implemented in Oni by using Throw/Catch:
Catch(['exit'],
Par(If(Not(F), Throw('exit', false)),
If(Not(G), Throw('exit', false))),
true)
A couple of footnotes:
- There is a slight problem with accidental capture of the Throw tag
from within F or G. This can be worked around though by using a host
language object as tag as described under http://croczilla.com/oni/reference/#throw-catch
.
- Using Throw/Catch to express local exits is really overkill. We
don't need a dynamically scoped construct for this - something like a
'Return' operator would be more appropriate, but we don't have that in
Oni (yet). There is Loop/Break though, so another (equally
unsatisfactory) way of expressing Parallel-Or would be:
Loop(Par(If(Not(F), Break(false)),
If(Not(G), Break(false))),
Break(true))
- If we want to wrap Parallel-Or into a function, F and G need to be
functions too. This is because functions in Oni are strict, and for
Parallel-Or we need to take the evaluation strategy into our own
hands. A function-based implementation would look like this:
var POR =
Defun(['F', 'G'],
Catch(['exit'],
Par(If(Not(Exec(Get('F'))), Throw('exit', false)),
If(Not(Exec(Get('G'))), Throw('exit', false))),
true))
If we want Parallel-Or to be an operator that takes Oni *expressions*
as arguments, we can use JavaScript as a kind-of macro language:
var POR =
function(F, G) {
var tag = {};
return Catch(tag,
Par(If(Not(F), Throw(tag, false)),
If(Not(G), Throw(tag, false))),
true));
}
(Here we're using an object as Throw tag to prevent accidental capture.)
One of the reasons why I want to make Oni non-strict is so that we can
use normal functions to implement operators.
Regards,
Alex
> [...]
> Parallel-Or can be implemented in Oni by using Throw/Catch:
>
> Catch(['exit'],
> Par(If(Not(F), Throw('exit', false)),
> If(Not(G), Throw('exit', false))),
> true)
>
Oops, obviously I'm not quite awake yet. This is Parallel-*And*, of
course :-)
Here's Parallel-Or:
Catch(['exit'],
Par(If(F, Throw('exit', true)),
If(G, Throw('exit', true))),
false)
Regards,
Alex
Yes, fortunately there is a better way :-)
It's a little bit easier with Throw/Catch, because that allows us to
omit one outer Let-clause:
Catch(['exit'], Min(Let({x: GetNextLaptop()},
If(Lt(Get('x'),100), Throw('exit', Get('x')))),
Let({x: GetAnotherLaptop()},
If(Lt(Get('x'),100), Throw('exit',
Get('x'))))));
Why does this work? Min is a function, and the semantics of function
application in Oni are that the arguments get evaluated in parallel
before being passed into the function. In fact, 'Par' is just a
function that throws away its arguments and returns something
undefined. It is a synonym for Nop:
var Nop = SLift(function(){/* do nothing */});
var Par = Nop;
Regards,
Alex