From p.singleton@keele.ac.uk  Fri May 19 18:37:57 2000
Received: from cmailg4.svr.pol.co.uk (cmailg4.svr.pol.co.uk [195.92.195.174])
	by swi.psy.uva.nl (8.9.3/8.9.3) with ESMTP id SAA12013;
	Fri, 19 May 2000 18:37:57 +0200 (MET DST)
Received: from modem4294967185.firearms.dialup.pol.co.uk ([195.92.2.239] helo=keele.ac.uk)
	by cmailg4.svr.pol.co.uk with esmtp (Exim 3.13 #0)
	id 12spmz-0000wb-00; Fri, 19 May 2000 17:38:17 +0100
Message-ID: <39256DA9.DAE66520@keele.ac.uk>
Date: Fri, 19 May 2000 17:36:57 +0100
From: Paul Singleton <p.singleton@keele.ac.uk>
Organization: SmartArts Computing Consultancy
X-Mailer: Mozilla 4.7 [en] (WinNT; I)
X-Accept-Language: en
MIME-Version: 1.0
To: Jan Wielemaker <jan@swi.psy.uva.nl>, SWI Prolog <prolog@swi.psy.uva.nl>
Subject: non-determinism & cleanup [was: Fwd: Non-redundant wrappers?]
References: <200005181416.QAA08958@gollem.swi.psy.uva.nl>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> 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.

