[comp.lang.prolog] The touchstone applied to "The Art of Prolog"

ok@cs.mu.oz.au (Richard O'Keefe) (11/08/89)

Just to show that I haven't got my knife exclusively into WG17,
here's a report on what I found when I applied the "touchstone"
(how does the book explain findall/bagof/setof, does their code
work) to the book "The Art of Prolog" by Sterling and Shapiro.

/*  This is Program 17.3  "Implementing a set predicate using
			   difference-lists, assert, and retract"
    from section 17.1, page 270, of "The Art of Prolog" by
    Sterling and Shapiro, 1986.
*/

find_all_dl(X, Goal, Xs) :-		% Bug 4 (Xs should be Xs-Ys, or)
	asserta('$instance'('$mark')),	% Bug 1 ($mark looks like a solution)
	Goal,
	asserta('$instance'(X)),	% Bug 1 ($mark looks like a solution)
	fail.
find_all_dl(X, Goal, Xs-Ys) :-		% Bug 4 (Xs-Ys should be Xs)
	retract('$instance'(X)),	% Bug 2 (X becomes last answer or $mark)
	reap(X, Xs-Ys),
	!.				% Bug 3 (cut should precede reap)

reap(X, Xs-Ys) :-
	X \== '$mark',
	retract('$instance'(X1)),
	!,
	reap(X1, Xs-[X|Ys]).
reap('$mark', Xs-Xs).


/*  The following tests illustrate problems with that definition
*/

test_1 :-			% Bug 2
	find_all_dl(., fail, L),
	write(L).		% Should be Z-Z
				% INSTEAD:  fails,
				% and leaves $instance($mark) in data base.

test_2 :-			% Bug 2
	find_all_dl(X, fail, L),
	write((X, L)).		% Should be _, Z-Z
				% INSTEAD:  '$mark', Z-Z

test_3 :-			% Bug 2
	find_all_dl(X, (X = *;X = /), L),
	write((X, L)).		% Should be _, [*,/|Z]-Z
				% INSTEAD:  /, [*,/|Z]-Z

test_4 :-			% Bug 1
	find_all_dl(X, (X = '$instance';X = '$mark'), L),
	write(L).		% Should be ['$instance','$mark'|Z]-Z
				% INSTEAD:  Z-Z, and leaves
				% $instance($instance), $instance($mark)
				% behind in the data base.

/*  This looks as though the inner find_all_dl is stealing solutions
    from the outer one, but in fact the problem is the *extra*
    $instance($mark) it leaves behind.
*/
test_5 :-			% Bug 4
	find_all_dl(X, (X = a ; X = b ; X = c ;
	    find_all_dl(Y, fail, *), X = d), L),
	write(L).		% Should be [a,b,c|Z]-Z
				% INSTEAD:  Z-Z, and leaves
				% $mark, a, b, c in $instance data base.

/*  The text says 'Asserting "$mark" is essential for nested
    set-expressions to work correctly, lest one set would "steal"
    solutions produced by the other set-expression.'  test_5
    shows how an inner find_all_dl _may_ steal (all the) solutions
    from an outer find_all_dl.
*/
test_6 :-			% Bug 3 and Bug 4
	find_all_dl(X, (X = a ; X = b ; X = c ;
	    find_all_dl(Y, fail, x-y), X = d), L),
	write(L).		% Should be [a,b,c|Z]-Z
				% INSTEAD:  fails, and leaves
				% the data base empty.
end_of_file.