Prolog中的指令顺序和递归
Posted
技术标签:
【中文标题】Prolog中的指令顺序和递归【英文标题】:Order of instructions and recursion in Prolog 【发布时间】:2022-01-10 05:53:47 【问题描述】:我刚从 prolog 开始,我有一个关于递归的问题。
我基本上想计算某个值在列表中出现的次数, 所以我有例如:
count( a, [ a, s, d, f, g, a, s, d, a, s ], W ). W = 3.
我想计算“a”在列表中出现的次数并将数字存储在“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 ).
但是,我不明白为什么在第 2 行中,最后是“X 是 Y+1”。 这条线不应该是
count( A, [A|S], X ) :- Y is X + 1, count( A, S, Y ).
在这种情况下,我们首先将 Y 设置为 1,然后通过递归再次将其发送到“count”。
如果有人可以帮助我,我将不胜感激!
【问题讨论】:
【参考方案1】:请考虑当您调用时:
?- count(a,[a,s,d,f,g,a,s,d,a,s],W).
...那么第一个匹配的谓词是count(A,[B|S],X)
。这意味着它看起来像count(a,[a|S],X)
,其中S
和X
是变量。 X
只是来自原始调用的W
,所以它仍然是一个变量。
建议然后评估 Y is X + 1
是没有意义的,因为 X
是一个变量。
然而,原来的谓词确实有意义。
count(A,[B|S],X) :- A==B, count(A,S,Y), X is Y + 1.
当它递归时,它将一个新变量Y
发送到第二个count/3
谓词中(或者只是在第三个谓词中传递相同的变量)。它会一直这样做,直到它最终将变量统一为0
时达到基本情况。此时它展开递归,现在它终于可以执行X is Y + 1
(因为Y
是一个值),因此X
现在是一个值。
Prolog 是一门有趣的语言,因为它几乎有一种时间旅行的感觉,您必须向前和向后思考才能理解程序的工作原理。
【讨论】:
哇,现在我明白了!非常感谢!【参考方案2】:count( A, [B|S], X ) :- A==B, count( A, S, Y ), X is Y + 1.
这意味着:如果S
包含Y
出现的A
和A == B
,则[B | S]
包含更多的A
。
例如,假设我们正在计算prolog
在[prolog, prolog, prolog]
中的出现次数。 [B | S] = [prolog, prolog, prolog]
,所以S = [prolog, prolog]
。 prolog
在S
中出现的次数是2,所以我们应该有Y = 2
。在[B | S]
中prolog
的出现次数是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]
包含X
出现的A
,那么S
包含更多的A
。这不可能。
再次使用上面的例子:显然[A | S] = [prolog, prolog, prolog]
包含3 个prolog
,所以X = 3
应该成立。但是Y
必须是 4,并且正文中的目标会尝试证明 S = [prolog, prolog]
包含 4 次出现的 prolog
。显然情况并非如此。
请注意,这个解释只是关于谓词的含义。它不需要我们考虑递归、目标顺序或程序实际执行的确切方式。在进行 Prolog 编程时,首先要弄清楚程序的逻辑含义。
【讨论】:
以上是关于Prolog中的指令顺序和递归的主要内容,如果未能解决你的问题,请参考以下文章