10.1 General

The module Value contains the following general control procedures.

Wait

{Value.wait +X}

blocks until X is determined. This statement makes X needed, causing all by-need computations on X to be triggered. If X is or becomes bound to a failed value, then its encapsulated exception is raised.

WaitOr

{Value.waitOr X Y}

blocks until at least one of X or Y is determined.

waitQuiet

{Value.waitQuiet +X}

blocks until X is determined or failed. Contrary to Wait, Value.waitQuiet does not make X needed. Also, if X is or becomes bound to a failed value, no exception is raised.

!!

{Value.'!!' X Y}

returns a future Y for X, i. e., a read-only placeholder for X. If Y becomes needed, X is made needed too.

WaitNeeded

{Value.waitNeeded X}

blocks until X is needed. This operation is the by-need synchronization.

IsNeeded

{Value.isNeeded X ?B}

tests whether X is needed.

makeNeeded

{Value.makeNeeded X}

makes X needed. This statement is useful for triggering by-need computations on X with having to suspend on X.

ByNeed

{Value.byNeed P X}

concurrently evaluates {P X} as soon as X becomes needed. It can be defined as follows:

proc {ByNeed P X}
   thread {WaitNeeded X} {P X} end 
end

ByNeedFuture

{Value.byNeedFuture P X}

creates a by-need computation that evaluates the expression {P}, and returns a future X of its result. If the call to P raises an exception E, then X is bound to a failed value (see below) that encapsulates E. It can be defined as follows:

fun {ByNeedFuture P}
   !!{ByNeed fun {$}
                try {P} catch E then {Value.failed E} end 
             end}
end

failed

{Value.failed E X}

creates a failed value X encapsulating exception E. Whenever a statement needs X, in particular, whenever a thread synchronizes on X, exception term E is raised. This is convenient in concurrent designs: if a concurrent generator encounters a problem while computing a value, it may catch the corresponding exception, package it as a failed value and return the latter instead. Thus each consumer will be able to synchronously handle the exception when it attempts to use the ``failed'' value. For example, the module manager returns failed futures for modules that cannot be found or linked.

The failed value X can only unify to itself. An attempt to unify X to any other value results in exception E to be raised. Unifying two distinct failed values causes one of them to raise its exception, the choice of which being nondeterministic.


Denys Duchier, Leif Kornstaedt and Christian Schulte
Version 1.4.0 (20080702)