From jan@swi.psy.uva.nl  Fri May 19 21:51:22 2000
Received: from gollem.swi.psy.uva.nl (root@gollem [145.18.152.30])
	by swi.psy.uva.nl (8.9.3/8.9.3) with ESMTP id VAA15229;
	Fri, 19 May 2000 21:51:22 +0200 (MET DST)
Received: (from jan@localhost)
	by gollem.swi.psy.uva.nl (8.9.3/8.9.3/SuSE Linux 8.9.3-0.1) id VAA12437;
	Fri, 19 May 2000 21:51:42 +0200
Date: Fri, 19 May 2000 21:51:42 +0200
Message-Id: <200005191951.VAA12437@gollem.swi.psy.uva.nl>
From: Jan Wielemaker <jan@swi.psy.uva.nl>
Subject: Re: non-determinism & cleanup [was: Fwd: Non-redundant wrappers?]
To: Paul Singleton <p.singleton@keele.ac.uk>,
        Jan Wielemaker <jan@swi.psy.uva.nl>,
        SWI Prolog <prolog@swi.psy.uva.nl>
In-Reply-To: Paul Singleton's message of Fri, 19 May 2000 17:36:57 +0100
Phone: +31 - 20 - 525 6121

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

On PL_REDO, the argument vector is the same as on PL_FIRST_CALL.  On
PL_CUTTED, the arguments, except for the context arguments are
undefined.  The context returns whatever you returned from the last
nondeterministic success.  PL_CUTTED is invoked on ! as well as on
exceptions (is there any reason to distinguish?).

	Regards --- Jan

