Prolog中的指令顺序和递归
Order of instructions and recursion in 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 is Y+1”。
该行不应该是
count( A, [A|S], X ) :- Y is X + 1, count( A, S, Y ).
在那种情况下,我们首先将 Y 设置为 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 是一种有趣的语言,因为它几乎具有时间旅行的感觉,您必须向前和向后思考才能理解程序的工作原理。
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]
。 S
中prolog
出现的次数是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 编程时,尽量先弄清楚程序的逻辑含义。
我刚开始学习序言,我有一个关于递归的问题。
我基本上想计算某个值在列表中出现的次数, 所以我有例如:
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 is Y+1”。 该行不应该是
count( A, [A|S], X ) :- Y is X + 1, count( A, S, Y ).
在那种情况下,我们首先将 Y 设置为 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 是一种有趣的语言,因为它几乎具有时间旅行的感觉,您必须向前和向后思考才能理解程序的工作原理。
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]
。 S
中prolog
出现的次数是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 编程时,尽量先弄清楚程序的逻辑含义。