BinProlog 5.75 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/0 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.