Miranda order

From Erights

(Difference between revisions)
Jump to: navigation, search
(let's have an explicit verb type)
(Documentation from MirandaMethods.java (licensed by MarkM's stated blanket permission))
Line 1: Line 1:
-
{{instance msgdoc|__order|2|<var>verb</var> :[[Verb]], <var>args</var> :[[List]]|[[any]]}}
+
{{instance msgdoc|__order|2|<var>verb</var> :[[String]], <var>args</var> :[[List]]|[[any]]}}
'''__order/2''' is a [[Miranda message]] for sending messages contingent on an earlier success.
'''__order/2''' is a [[Miranda message]] for sending messages contingent on an earlier success.
Line 54: Line 54:
If put throws, then <var>pairVow</var> will resolve directly to broken, so newDB
If put throws, then <var>pairVow</var> will resolve directly to broken, so newDB
will likewise resolve to broken, as will <var>value2Vow</var>.
will likewise resolve to broken, as will <var>value2Vow</var>.
-
 
-
===Distinguishing unresolved response from unresolved value===
 
-
 
-
It is also possible to use __order to observe when the turn caused by an eventual send finishes, even if its return value is itself an unresolved promise, by waiting for the returned tuple, or its second element, to resolve.
 
[[Category:Miranda messages]]
[[Category:Miranda messages]]
[[Category:Pluribus]]
[[Category:Pluribus]]

Revision as of 03:59, 1 August 2011

__order/2

Signature: __order(verb :String, args :List) :any

__order/2 is a Miranda message for sending messages contingent on an earlier success.

This method does the equivalent of

   to __order(verb, args) :any {
       [E.call(self, verb, args), self]
   }

In other words, it calls the receiving object with the message verb(args...), and, if successful, returns a pair of the result of this call and the receiving object itself.

What is this for? Consider the client code fragment

    databaseRcvr <- put(key1, value1)
    def value2Vow := databaseRcvr <- get(key2)

E's partial ordering semantics ensure that put will be delivered before get is delivered. That is often good enough. But it is a weaker guarantee than that provided by the following sequential code

    database put(key1, value1)
    def value2Vow := database get(key2)

In this code, not only will get only happen after put is delivered, get will only happen after put succeeds. If put instead throws an exception, the get will never happen. Often we want this effect. How can we achieve this with eventual-sends to eventual references?

When one wants to take an action contingent on the results of a previous action, the conventional E answer is to use a when-catch-finally expression

   def ackVow := databaseRcvr <- put(key1, value1)
   def value2Vow := when (ackVow) -> {
       databaseRcvr <- get(key2)
   } catch problem {
       throw(problem)
   }

This is fine, as is probably the solution to be used by default for this situation. However, it does force a round-trip between the get and put, and so loses the benefits of pipelining. Using the __order message, we can get contingent execution + pipelining, at some cost in obscurity. (Note: often, the cost of obscurity will dominate.)

   def pairVow := databaseRcvr <- __order("put", [key1, value1])
   # If put's return value were interesting, we'd 'pairVow <- get(0)'
   def newDBRcvr := pairVow <- get(1)
   def value2Vow := newDBRcvr <- get(key2)

If put throws, then pairVow will resolve directly to broken, so newDB will likewise resolve to broken, as will value2Vow.

Personal tools
more tools