Reputation: 91
I want to define a predicate in Prolog, prod_list/2 that multiplies every element of a list. I'm having problem with the empty list wish the product should be zero, instead i get false. My code is
prod_list([H], H).
prod_list([H|T], Product) :- prod_list(T, Rest),
Product is H * Rest.
The results I get are prod_list([4,3],Product). -> Product = 12 but when I do prod_list([], Product). I get false instead of Product = 0.
Please help.
Upvotes: 0
Views: 8734
Reputation: 27424
Your problem is that no clause matches the empty list. In fact you have a recursive clause:
prod_list([H|T], Product) :- prod_list(T, Rest),
Product is H * Rest.
but its recursion terminates when there is only an element in the list:
prod_list([H], H).
So, in no case the empty list []
is matched by a clause, and for this reason, the answer is false
(no match available).
To solve your problem you need to include an explicit clause for the empty list:
prod_list([],0).
prod_list([H],H).
prod_list([H|T], Product) :- prod_list(T, Rest), Product is H * Rest.
A different solution could be found considering that the product of an empty list should be (correctly) defined in this way:
product_of_list([], 1).
product_of_list([H|T], Product) :- product_of_list(T, Rest), Product is H * Rest
then you could add your “special” definition of prod_list
:
prod_list([],0).
prod_list(List, Product) :- product_of_list(List, Product).
Edit
The last solution does not work for some interactive versions of Prolog (for instance Swish on-line), while it does work for SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.11). A solutions that should work for every version is the following:
prod_list([],0).
prod_list([H|T], Product) :- product_of_list([H|T], Product).
Thanks to user474491 for discovering this.
Upvotes: 7
Reputation: 29011
Renzo's answer is perfect. I just thought of functional treatment of lists when I saw your question. You can have them just in case you need them. If you define a function multiplication:
mul(V1,V2,R) :- R is V1*V2;
then you can use foldl in any of its variants:
?- foldl(mul, [1,2,10], 1, R).
R = 20 .
fold
is a traditional functional calculation function that applies a function accumulating the temporal result.
Upvotes: 4