Reputation: 11
I have this predicate to get the sum of the length of all borders of a country. I could solve it with findall but I have to use setof. My facts look like this:
borders(sweden,finland,586).
borders(norway,sweden,1619).
My code
circumference(C, Country) :-
findall(X, ( borders(Country, _, X) ; borders(_, Country, X)), Kms),
sum_list(Kms, C).
Upvotes: 1
Views: 183
Reputation: 11
I ended up using this:
circumference(Z, Country) :- setof(X, Q^(borders(Q,Country,X);borders(Country,Q,X)),Border),
sum_list(Border,Z).
% Adds the numbers in a list.
sum_list([], 0).
sum_list([H|T], Sum) :-
sum_list(T, Rest),
Sum is H + Rest.
Upvotes: 0
Reputation: 2422
You cannot find the sum using bagof
directly, all you can do is make a list and then sum that list (but you knew that already). In SWI-Prolog there is library(aggregate) that does the bagging and the summing for you. With the facts you have, you would write:
?- aggregate(sum(X), Y^( borders(Y, sweden, X) ; borders(sweden, Y, X) ), Circumference).
Circumference = 2205.
If you instead must obey the whims of your instructor and type "bagof" yourself, or if you are not allowed to use a modern, open source, comprehensive Prolog implementation, you can use the same approach with bagof
and manually build the list before summing it:
?- bagof(X, Y^( borders(Y, sweden, X) ; borders(sweden, Y, X) ), Borders).
Borders = [1619, 586].
For reasons that are lost in the mists of time the funny thing with the Var^Goal
that you see in both aggregate
and bagof
is called "existentially qualifying the variables in Goal". You might also read that "^
prevents binding Var in Goal". I cannot explain what this really means.
Upvotes: 1