## 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.