Prolog 将列表的所有元素相乘

Prolog multiply all elements of a list

我想在 Prolog 中定义一个谓词,prod_list/2 将列表的每个元素相乘。我对空列表有疑问,希望产品应该为零,但我得到的是错误的。 我的代码是

prod_list([H], H).
prod_list([H|T], Product) :- prod_list(T, Rest), 
                            Product is H * Rest.

我得到的结果是 prod_list([4,3],产品)。 -> 产品 = 12 但是当我做 prod_list([], Product) 时。我得到的是 false 而不是 Product = 0。

请帮忙。

您的问题是 no 子句匹配空列表。事实上你有一个递归子句:

prod_list([H|T], Product) :- prod_list(T, Rest), 
                        Product is H * Rest.

但是当列表中只有一个元素时它的递归终止:

prod_list([H], H).

因此,在任何情况下,空列表 [] 都不会与子句匹配,因此,答案是 false(无匹配项)。

要解决您的问题,您需要为空列表包含一个显式子句:

prod_list([],0).
prod_list([H],H).
prod_list([H|T], Product) :- prod_list(T, Rest), Product is H * Rest.

考虑到应该(正确)以这种方式定义空列表的乘积,可以找到不同的解决方案:

product_of_list([], 1).
product_of_list([H|T], Product) :- product_of_list(T, Rest), Product is H * Rest

然后你可以添加你对 prod_list 的“特殊”定义:

prod_list([],0).
prod_list(List, Product) :- product_of_list(List, Product).

编辑

最后一个解决方案不适用于 Prolog 的某些交互式版本(例如在线 Swish),而 SWI-Prolog(多线程)有效, 64 位,版本 7.3.11)。适用于每个版本的解决方案如下:

prod_list([],0).
prod_list([H|T], Product) :- product_of_list([H|T], Product).

感谢 user474491 发现这一点。

Renzo 的回答很完美。当我看到你的问题时,我只是想到了列表的功能处理。您可以拥有它们以备不时之需。如果定义函数乘法:

mul(V1,V2,R) :- R is V1*V2;

然后你可以在它的任何变体中使用 foldl:

?- foldl(mul, [1,2,10], 1, R).
R = 20 .

fold是一个传统的函数式计算函数,它应用了一个累积时间结果的函数。