Prolog将列表中的所有元素相乘

Prolog将列表中的所有元素相乘,prolog,logic-programming,Prolog,Logic Programming,我想在Prolog中定义一个谓词prod_list/2,它将列表中的每个元素相乘。我有空列表的问题,希望产品应该是零,而不是我得到假。 我的代码是 prod_list([H], H). prod_list([H|T], Product) :- prod_list(T, Rest), Product is H * Rest. 我得到的结果是 产品清单([4,3],产品)。->产品=12 但当我做prod_list([],Product)时

我想在Prolog中定义一个谓词prod_list/2,它将列表中的每个元素相乘。我有空列表的问题,希望产品应该是零,而不是我得到假。 我的代码是

prod_list([H], H).
prod_list([H|T], Product) :- prod_list(T, Rest), 
                            Product is H * Rest.
我得到的结果是 产品清单([4,3],产品)。->产品=12 但当我做prod_list([],Product)时。我得到的是false,而不是Product=0

请帮忙

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

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([],0).
prod_list(List, Product) :- product_of_list(List, Product).
编辑

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

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

感谢用户474491发现了这一点。

伦佐的答案非常完美。当我看到你的问题时,我想到了列表的函数处理。你可以拿着它们,以防万一。如果定义函数乘法:

mul(V1,V2,R) :- R is V1*V2;
然后,您可以在其任何变体中使用foldl:

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

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

如果有一个子句用于一个元素的列表,请为空列表添加一个子句。为什么您认为
[]
的乘积应该是
0
?看到这一点。我认为最后一个解决方案将为空列表返回两个结果:0和1。@user474491,如果您尝试它,您将发现它只返回值0。我刚刚在Swish Online上进行了尝试,我确实得到了两个prod_list([],Result)的结果,正如预期的那样。我在(多线程,64位,版本7.3.11)上进行了尝试,它只给出了一个结果。可能是不同的语义?因为最好有一个始终有效的解决方案,所以我更新了答案。感谢@user474491报告问题。或者
foldl(\V1^V2^R^(R是V1*V2),[1,2,10],1,Rx)。
当然,但这需要lambda模块,对吗?