question regarding Let+Alt

8 views
Skip to first unread message

Adrian Quark

unread,
Apr 16, 2009, 3:46:56 PM4/16/09
to Oni - embedded structured concurrency
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 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.

Alexander Fritze

unread,
Apr 17, 2009, 6:47:08 PM4/17/09
to oni-...@googlegroups.com
Hi Adrian,

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

Adrian Quark

unread,
Apr 20, 2009, 5:21:34 PM4/20/09
to Oni - embedded structured concurrency
On Apr 17, 5:47 pm, Alexander Fritze <a...@croczilla.com> wrote:
> 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!

If you have mutable state and blocking, you can always implement
futures as a library. But I think the main advantage of futures as
provided by the Orc <x< combinator is not expressiveness, but ease of
analysis. Unlike a future implemented in a library, a future
introduced by <x< can only be used to communicate in one direction
between independent evaluation contexts, so it can't introduce
deadlocks.

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

> I have some longer term plans of making Oni mostly non-strict like  
> Haskell.

That sounds interesting, I'll look forward to seeing that.

Adrian Quark

unread,
Apr 20, 2009, 5:21:34 PM4/20/09
to Oni - embedded structured concurrency
On Apr 17, 5:47 pm, Alexander Fritze <a...@croczilla.com> wrote:
> 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!

If you have mutable state and blocking, you can always implement
futures as a library. But I think the main advantage of futures as
provided by the Orc <x< combinator is not expressiveness, but ease of
analysis. Unlike a future implemented in a library, a future
introduced by <x< can only be used to communicate in one direction
between independent evaluation contexts, so it can't introduce
deadlocks.

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

> I have some longer term plans of making Oni mostly non-strict like  
> Haskell.

Alexander Fritze

unread,
Apr 21, 2009, 3:19:41 AM4/21/09
to oni-...@googlegroups.com

On 20. Apr2009, at 23:21 , Adrian Quark wrote:

>
> [...]


> 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

Alexander Fritze

unread,
Apr 21, 2009, 3:28:09 AM4/21/09
to oni-...@googlegroups.com

On 21. Apr2009, at 9:19 , Alexander Fritze wrote:

> [...]


> 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

Adrian Quark

unread,
Apr 21, 2009, 10:48:31 AM4/21/09
to Oni - embedded structured concurrency
That's neat, but it seems like it might get complicated if you have a
more interesting operator than OR. For example, let's say you're
buying a laptop on eBay, and you'll buy the first laptop you find
under $100, or the cheapest otherwise. In Orc this has the same
structure as parallel-or, with "< 100" instead of "= true" and "min"
instead of "||".

I tried to encode this in Oni, but couldn't avoid mutable variables:

// assuming suitable defs of Write, Read, Lt, and Min; untested
var f, g;
Loop(Par(Seq(Write(f, GetNextLaptop()), If(Lt(Read(f), 100), Break
(f))),
Seq(Write(g, GetMoreLaptops()), If(Lt(Read(g), 100), Break
(g)))),
Break(Min(Read(f), Read(g))))

Do you know a better way?

Alexander Fritze

unread,
Apr 21, 2009, 11:57:15 AM4/21/09
to oni-...@googlegroups.com


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

Adrian Quark

unread,
Apr 21, 2009, 5:07:44 PM4/21/09
to Oni - embedded structured concurrency
That's great. It looks like Oni can express all the typical Orc idioms
despite lacking futures.
Reply all
Reply to author
Forward
0 new messages