Next: , Previous: , Up: prolog-libraries   [Index]

16.13.2 Delimited continuation goals.

Continuations are a freezed state that is encapsulated by a lambda and can resstart at the stored location when one executes the lambda. Delimited continuations means that one can compose the continuations freely and basically mean thta from a control point the continuation evaluation returns what the lambda inside the control point returns, delimited continuations can therefore be construted and used like any other funciton in a composable way, normal continuatins can be more difficult to handle and does not compose nicely. The delimited continuation goal will fail if the enclosing code fails and it will fail according to the new setup. Also when a delimeted continuation goal succeeds if the continuated enclosed code suceeds (that we restarted in) and the goal works just like any other goal. Api

with_prompt(tag,code,handler_data,handler), The enclosing code is code, which will first executed, if inside this, a abort_to_prompt is executed with a tag, matching this ideoms tag, then the handler will be executed with handler_data unified to,

handler_data = [intag,next,kont,data_from_abort], The actual intag will be intag. A goal, next(), will be supplied which can be used to instruct the code to search for the next handler if executed. The actual continuation goal kont, is supplied as well as data send from the abort_to_prompt in data_from_abort. kont is a term with one argument and is executed like call_k(kont,Arg), sending an Arg to the restart to the continuation. kont is live for the rest of the execution and the handler will at backtracking fail the whole with_promt ideom.

call_k(kont,A), execute a continuation goal.

abort_to_prompt(tag,data_to_handler, data_from_continuation), will abort with tag tag, for which a handler is searched. data_to_handler, is data sent to the handler, and data_from_continuation, is the data that is put inside the argument of the continuation.

re_prompt(tag,kont,handle_data handle kont_data))

re_prompt(kont,handle_data handle kont_data)) (old tag is reused),

an efficiency hack to handle the case when a continuation is executed, but with a new handler in stead of the old one that that continuation came from. This is useful because with this a generator built with this tool does not build up stack. Example:

(use-modules (logic guile-log guile-prolog continuations))

/* produce a value X to the user */
yield(X) :- abort_to_prompt(generator,X,_).

/* consume a value X from the user */
eat(X)   :- abort_to_prompt(generator,_,X).

/* execute Goal and put the resulting generator state in F */
generator(Goal,F) :- 
       with_prompt(generator, Goal,[generator,_,K,X], F=[K,X]).

/* [K,X] is the state argument, X will be the next value argument, F will
   bind to the new state */
next([K,X],X,F)        :- re_prompt(K,[generator,_,K2,XX],F=[K2,XX],_).

/* same as next, but Y will be a value fed to the consumer generator */
feed([K,_],Y,F)        :- re_prompt(K,[generator,_,K2,_ ],F=[K2,_ ],Y).

/* the full two way ideom */
translate([K,X],X,Y,F) :- re_prompt(K,[generator,_,K2,XX],F=[K2,XX],Y).

/* sum consumes via eat(X) and add X to the S */
sum(S) :- eat(X),
          SS is S + X,

/* yields N,N+1,..,9 */
iter(N) :- N < 10 -> ( yield(N),
                       N2 is N + 1, 
                       iter(N2) ).

/* create a producer F and a consumer S */
run :-  generator(iter(0),F),       

/* transfers data from the producer to the feeder */
pr(F,S) :- next(F,X,FF) -> feed(S,X,SS), pr(FF,SS).

Next: , Previous: , Up: prolog-libraries   [Index]