Direct binary clause programming and full-blown continuations

BinProlog 3.30 supports direct manipulation of binary clauses denoted

   Head ::- Body.

They
give full power to the knowledgeable programmer on the future of the computation. Note that such a facility is not available in conventional WAM-based systems where continuations are not first-order objects.

We can use them to write programs like:

  member_cont(X,Cont)::-
    strip_cont(Cont,X,NewCont,true(NewCont)).
  member_cont(X,Cont)::-
    strip_cont(Cont,_,NewCont,member_cont(X,NewCont)).

  test(X):-member_cont(X),a,b,c.

A
query like
  ?-test(X).

will
return X=a; X=b; X=c; X=whatever follows from the calling point of test(X).

catch(Goal,Name,Cont)::-
   lval(catch_throw,Name,Cont,call(Goal,Cont)).

throw(Name,_)::-
   lval(catch_throw,Name,Cont,nonvar(Cont,Cont)).

where
lval(K1,K2,Val) is a BinProlog primitive which unifies Val with a backtrackable global logical variable accessed by hashing on two (constant or variable) keys K1,K2.

This allows for instance to avoid execution of the infinite loop from inside the predicate b/1.

loop:-loop.

c(X):-b(X),loop.

b(hello):-throw(here).
b(bye).

go:-catch(c(X),here),write(X),nl.

Notice that due to its simple translation semantics this program still has a first order reading and that BinProlog's lval/3 is not essential as it can be emulated by an extra argument passed to all predicates.

Although implementation of catch and throw requires full-blown continuations, we can see that at user level, ordinary clause notation is enough.