Subject: Re: [SWIPL] I need help about my code

From: "Richard A. O'Keefe" <[email-masked]>
Date: Tue, 27 Mar 2001 14:09:58 +1200 (NZST)

Ryo Saeba <[email-masked]> has some facts for
    course_name(CourseCode, NameAsAtom)
    person_course(PersonID, Year, Semester, CourseCode)
and wants a predicate
    p(PersonID)
that lists all the courses that person has taken.

	p(N) :- repeat, query.., print.., fail.

keeps on repeating the same output over and over.
But that's precisely what repeat/0 is SUPPOSED to do.

	p(N) :- query.., print.. .

writes just the first course, again doing EXACTLY what it should.

However,

    p(N) :-
	person_course(N, _, _, C),
	course_name(C, CT),
	write(C), write(' '), write(CT), nl,
	fail ; true.

uses a "failure-driven loop" to backtrack over all ways of satisfying
the query, printing each.

Better style would be to package this up like so:
	
    % forall(+Generator: void, +Test: void)
    % succeeds when there is no proof of Generator for which
    % the corresponding instance of Test fails.
    % Unbound variables are (again) unbound on exit.

    forall(Generator, Test) :-
        call(( Generator, ( Test -> fail ; true ) -> fail ; true )).

    print_course(C) :-
	course_name(C, CT),
	write(C), write(' '), write(CT), nl.
	
    p(N) :-
	forall(person_course(N, _, _, C), print_course(C)).