Subject: non-determinism & cleanup [was: Fwd: Non-redundant wrappers?]

From: Paul Singleton <[email-masked]>
Date: Fri, 19 May 2000 17:36:57 +0100

> In other words, if you have a deterministic get-first, get-next and
> cleanup you can use SWI-Prolog foreign code to construct a
> non-deterministic predicate that is guaranteed to call cleanup.

...or open/get/close, as in:

  generate(A, B) :-
      open(A, X),
      generate_1(X, B).

  generate_1(X, B) :-
      get(X, B1),    % failure indicates no more Bs
      (    B = B1
      ;    generate_1(X, B)
      ).

  close(X) :-        % we want this called automatically

OK, this idiom isn't completely general (?), but it's common enough so I've
implemented a generic foreign predicate

  cleanup_open_get_close(OpenPredName, GetPredName, ClosePredName, In, Out) :-
    % a PL_FA_NONDETERMINISTIC foreign function using PL_call_predicate()
    % on OpenPredName/2, GetPredName/2, ClosePredName/1

and have tested it by generating the chars of a file, closing the stream on
cut etc.

  file_char(F, C) :-
      cleanup_open_get_close(p1, p2, p3, F, C).

  p1(A, X) :-
      open(A, read, S).

  p2(X, B) :-
      get0(X, B),
      B \== -1.

  p3(X) :-
      close(X).

I'm saving the 'X' state from first call to redo with PL_record(X) - can I
stash a (maybe not always ground?) term in the context structure safely?

cheers - Paul S.