[cap-talk] async AND in E versus Joe-E/ref_send

Tyler Close tyler.close at gmail.com
Sun Mar 11 10:48:51 CDT 2007


So in an attempt to stoke the fires a bit, here's a side-by-side
comparison of asynchronous logical AND in E versus in Joe-E/ref_send.
First in E, from MarkM's thesis:

def asyncAnd (answers ) {
    var countDown := answers.size()
    if (countDown == 0) { return true }
    def [result , resolver ] := Ref.promise()
    for answer in answers {
        when (answer) -> {
            if (answer) {
                if ((countDown -= 1) == 0) { resolver.resolve(true) }
            } else {
                resolver.resolve(false)
            }
        } catch ex { resolver.smash(ex) }
    }
    return result
}

Now in Joe-E/ref_send:

    static public Promise<Boolean>
    and(final Eventual _, final Promise<Boolean>... condition) {
        if (0 == condition.length) { return ref(true); }
        final Channel<Boolean> x = _.defer();
        final Var<Integer> remaining = var(condition.length);
        for (final Promise<Boolean> test : condition) {
            _.when(test, new Do<Boolean,Void>() {
              public Void
              resolve(final Boolean value) {
                  if (value) {
                      remaining.put(remaining.cast() - 1);
                      if (0 == remaining.cast()) { x.head.resolve(true); }
                  } else {
                      x.head.resolve(false);
                  }
                  return null;
              }
              public Void
              reject(final Exception reason) { return x.head.reject(reason); }
           });
        }
        return x.tail;
    }

The above implementations are 15 and 23 lines respectively, making the
Joe-E/ref_send implementation about 50% longer. The difference in line
count primarily comes from E having special syntax for a when block,
whereas the Joe-E/ref_send implementation can only use Java's inner
class syntax. The big advantage of the Joe-E/ref_send implementation
is that it can be written and debugged using any Java IDE and runs
with Java's performance characteristics.

Also notice the extra parameter in the Joe-E/ref_send implementation,
the Eventual. The ref_send library is implemented in conforming Joe-E
code, and so cannot have static mutable state. This requirement means
that E's approach of making the event loop ambient authority cannot
work in ref_send. The event loop must be an explicit argument to
methods. So far, I haven't found this explicit argument passing too
much of a burden. This design also has the advantage that I can deny
some code access to the event loop. So for example, I can make a
library call and when it returns I know for sure that it is done
executing since it doesn't have access to the event loop, which would
enable it to schedule future execution.

In ref_send, I've appropriated the much maligned '_' character to
identify all eventual operations. The Eventual operator itself is by
convention held in a variable named "_", and all eventual references
are suffixed with an '_'. These conventions mean that the programmer
can quickly identify all the eventual operations in a body of code
just by scanning down the page looking for the '_' character. I think
this convention makes change in flow of control standout nicely from
the surrounding code, without being heavyweight.

Tyler


More information about the cap-talk mailing list