我正在prolog中读取一个递归函数,它返回列表中所有元素的Sum,如下所示:
sum([ ], 0).
sum( [Elem | Tail], S):- sum(Tail, S1),
S is S1 + Elem.
我无法理解两个问题:
1:在“: - ”的左侧,我们有目标。这意味着所有计算都将在“: - ”的右侧完成,然后我们可以使用目标作为正常函数。这意味着我们给出我们的参数和变量,结果将被放在它们上面,右侧负责计算。
但在此代码中,目标本身正在计算头部和尾部。我的意思是在我看来代码应该是这样的(但它不起作用!):
sum(Tail, S1):-sum( [Elem | Tail], S),........
因为目标应该给出参数而右侧负责计算。
2:我无法理解这段代码是如何逐步运作的。任何人都可以给我一个非常简单的例子,比如它如何计算[1,2,3]的总和?
答案 0 :(得分:1)
prolog的一个重要部分是匹配(更一般地说,统一)。当Prolog运行时遇到像sum(X,Y)
这样的目标时,它会尝试将该术语与sum的规则的左侧(头部)按照它们出现的顺序进行匹配。如果第一个规则失败,则系统将移至第二个规则,依此类推。
在这种情况下,如果X是空列表,则第一个头只会匹配。如果它不为空,则匹配失败,并尝试下一个头。只要X是任何非空列表,这将成功。它不仅会成功,而且会将列表的第一个元素绑定到Elem
,列表的其余部分(可能为空)到Tail
。由于此规则头部的第二个参数是变量,因此它将绑定到Y是什么。
让我们通过一些例子来说明:
和([],X)?
第一个头匹配,将X绑定到0。
和([1],X)?
第一个头不匹配,因为[1]与[]不匹配。第二个是Elem< -1,Tail< - []。因此,我们可以继续执行规则的右侧:
sum(Tail,S1), S is S1 + Elem
由于Tail< - [],目标总和(Tail,S1)将产生绑定S1< -0(见上文)。因此,对于Elem< -1和S1< -0,S1 + Elem = 1。
等等。希望这里有足够的余下来做。
答案 1 :(得分:1)
在:-
的左侧,您有一个规则的头部;在右侧,你有规则的主体。当:-
侧和身体缺失时,规则变为事实。
说计算仅在正文中执行是不正确的,因为Prolog的决策过程适用于规则的两个方面。规则负责人扮演重要角色的概念是统一,这是一种语言决定哪些条款适用于查询的过程,并在规则头部中对变量进行检查和临时分配。查询的一部分(“统一”它们)。
例如,当您查询sum([1,2,3], X)
时,Prolog会检查两个sum
子句,并确定查询仅与第二个查询统一,因为[]
无法与{{1}统一}}
现在,我们需要将[1,2,3]
与[1,2,3]
统一起来,只要我们在规则正文中进行临时分配:[Elem | Tail]
和{{1} }。此时,它尝试再次解析Elem=1
,将Tail = [2,3]
作为第一个参数传递。第一条规则不匹配,因此进行了sum
和[2,3]
的另一个临时分配。在第三级递归中,我们达到了作业Elem=2
和Tail=[3]
。这是当我们达到第一个规则时,产生Elem=3
的赋值。第三级调用为其添加Tail=[]
;第二级添加S1=0
。第一级添加1,并返回时3
设置为2
。
答案 2 :(得分:0)
您对执行过程中发生的事情的猜测相当奇怪。根本没有任何功能。
为了评估目标sum([1,2,3], X)
,选择了第二个子句,因为[1,2,3]
(目标的第一个参数)和[]
之间没有匹配(在第一条)。
匹配实例化Elem=1
,Tail=[2,3]
和S = X
。然后评估目标sum([2,3], S1)
,并成功(在递归之后),返回替换S1=5
。然后S=5+1
将S
绑定到6。