[comp.lang.prolog] Programming techniques

lee@mulga.oz (Lee Naish) (03/17/88)

In article <772@cresswell.quintus.UUCP> ok@quintus.UUCP writes:
>
>use	q(0, X, X)	for an empty list
>and	q(s(s(...(0)...)), [X1,...,Xn|X], X)	for a list of N elements.
>
>	empty_queue(q(0,X,X)).
This is a really nice technique, which I only became aware of recently
(it was used in a breadth first search program of Fernando's posted to
the net).  I am currently giving an honours course on Prolog programming
techniques and gave this example last week (I used proper integers, not
s(...) - I think its better in this example).

There must be lots of techniques like this which are being discovered.
Please post them to the net so we can all benefit (including my
students).

Here is an example from todays lecture, for reading terms from a file
(the idea comes from David Morley):
 
        % Term is a term in File
        % (returns all terms in a file by backtracking)
        % Cleans up when eof is reached.
contains_term(File, Term) :-
        open(File, read, Stream),	% see(File),
        repeat,
        read(Stream, Term),		% read(Term),
        ( isEof(Term) ->
                close(Stream),		% seen,
                !,
                fail
        ).

contains_term/2 can be treated like a nice logical relation.
Some examples of its use:

	% get list of all terms in a file
read_all(File, TermList) :-
	findall(Term, contains_term(File, Term), TermList).

	% do dcg processing of a file
	% (I'm not sure if I like this style of coding)
dcg(File) :-
	contains_term(File, Term),
	expand_term(Term, ETerm),
	write_clause(ETerm),
	fail.
dcg(_).

Here is a better way of collecting all terms in a file into a single
term (a list in this case).  Most people should have seen this.

        % Treat file like a list of terms and use tail recursion to
        % process them.
        % This means we dont have to use side effects or all
        % solutions predicates to do something useful.
        % This scheme doesnt work properly with backtracking, since
        % read is not undone on backtracking.
read_all(File, AllTerms) :-
        open(File, read, Stream),
        read_all1(Stream, AllTerms).

read_all1(Stream, AllTerms) :-
        read(Stream, Term),
        ( isEof(Term) ->
                close(Stream),
                process_eof(AllTerms)
        ;
                process_term(Term, AllTerms, AllTerms1),
                read_all1(Stream, AllTerms1)
        ).
 
        % what to return at eof
process_eof([]).
 
        % how to return a single term in the data structure
process_term(Term, Term.AllTerms, AllTerms).

	lee