8.14 Coroutining

The coroutining facility can be accessed by a number of built-in predicates. This makes it possible to use coroutines in a dynamic way, without having to rely on block declarations:

`when(`+Condition`,`:Goal`)`
Blocks Goal until the Condition is true, where Condition is a goal with the restricted syntax:
`nonvar(`X`)`
`ground(`X`)`
`?=(`X`,`Y`)`
Condition`,`Condition
Condition`;`Condition

For example:

```          | ?- when(((nonvar(X);?=(X,Y)),ground(T)), process(X,Y,T)).
```

`freeze(`?X`,`:Goal`)`
Blocks Goal until `nonvar(`X`)` (see Meta Logic) holds. This is defined as if by:
```          freeze(X, Goal) :- when(nonvar(X), Goal).
```

or

```          :- block freeze(-, ?).
freeze(_, Goal) :- Goal.
```

`frozen(`-Var`,`?Goal`)`
If some goal is blocked on the variable Var, or Var has attributes that can be interpreted as a goal (see Attributes), then that goal is unified with Goal. If no goals are blocked, Goal is unified with the atom `true`. If more than one goal is blocked, a conjunction is unified with Goal.
`dif(`?X`,`?Y`)`
Constrains X and Y to represent different terms i.e. to be non-unifiable. Calls to `dif/2` either succeed, fail, or are blocked depending on whether X and Y are sufficiently instantiated. It is defined as if by:
```          dif(X, Y) :- when(?=(X,Y), X\==Y).
```

`call_residue(`:Goal`,`?Residue`) `obsolescent
The Goal is executed as if by `call/1`. If during the execution some attributes or blocked goals were attached to some variables, then Residue is unified with a list of VariableSet-Goal pairs, and those variables no longer have attributes or blocked goals attached to them. Otherwise, Residue is unified with the empty list `[]`.

VariableSet is a set of variables such that when any of the variables is bound, Goal gets unblocked. Usually, a goal is blocked on a single variable, in which case VariableSet is a singleton.

Goal is an ordinary goal, sometimes module prefixed. For example:

```          | ?- call_residue((dif(X,f(Y)), X=f(Z)), Res).

X = f(Z),
Res = [[Y,Z]-(prolog:dif(f(Z),f(Y)))]
```