我刚从prolog开始,我有一个关于递归的问题。
我基本上想计算某个值在列表中的时间,所以我有一个例子:
count( a, [ a, s, d, f, g, a, s, d, a, s ], W ). W = 3.
在我想计算时间的地方";a";在列表中,并将该号码存储在"0"中;W";。
正确答案是
count( _, [], 0 ).
count( A, [B|S], X ) :- A==B, count( A, S, Y ), X is Y + 1.
count( A, [B|S], X ) :- + A == B, count( A, S, X ).
Howhever,我不明白为什么在第2行;X是Y+1";最后。这条线不应该是吗
count( A, [A|S], X ) :- Y is X + 1, count( A, S, Y ).
在这种情况下,我们首先将Y设置为1,然后将其发送到"0";计数";再次使用递归。
如果有人能帮我,我将不胜感激!
当您调用:时,请考虑
?- count(a,[a,s,d,f,g,a,s,d,a,s],W).
则匹配的第一个谓词是CCD_ 1。这意味着它把它看作count(a,[a|S],X)
,其中S
&CCD_ 4是变量。X
只是来自原始调用的W
,因此它仍然是一个变量。
建议对Y is X + 1
进行评估是没有意义的,因为X
是一个变量。
然而,最初的谓词确实有意义。
count(A,[B|S],X) :- A==B, count(A,S,Y), X is Y + 1.
当它递归时,它将一个新的变量Y
发送到第二个count(A,[B|S],X)
0谓词中(或者只是在第三个谓词中传递相同的变量(。它一直这样做,直到它最终将变量统一到0
时达到基本情况。在这一点上,它取消了递归,现在它终于可以执行X is Y + 1
(因为Y
是一个值(,因此X
现在是一个数值。
Prolog是一种有趣的语言,因为它几乎有一种时间旅行的感觉,你必须向前和向后思考才能理解程序是如何工作的。
count( A, [B|S], X ) :- A==B, count( A, S, Y ), X is Y + 1.
这意味着:如果S
包含A
和A == B
的Y
次出现,则[B | S]
包含A
的一次出现。
例如,假设我们在计算[prolog, prolog, prolog]
中prolog
的出现次数时到达这里。[B | S] = [prolog, prolog, prolog]
和S = [prolog, prolog]
。prolog
在S
中的出现次数是2,所以我们应该有Y = 2
。prolog
在[B | S]
中的出现次数是3,所以我们应该有X = 3
。一旦我们知道Y = 2
,那么X is Y + 1
计算X
的这个正确值。
count( A, [A|S], X ) :- Y is X + 1, count( A, S, Y ).
这意味着:如果[A | S]
包含A
的X
次出现,则S
包含A
的一次出现。这不可能。
再次使用上面的例子:很明显,[A | S] = [prolog, prolog, prolog]
包含X
0的3次出现,所以X = 3
应该成立。但是Y
必须是4,并且体内的目标将试图证明S = [prolog, prolog]
包含4prolog
的出现。事实显然并非如此。
请注意,这个解释只是关于谓词的含义。它不需要我们考虑递归、目标的顺序或程序实际执行的确切方式。在进行Prolog编程时,首先要清楚程序的逻辑含义。