【发布时间】:2011-02-16 06:47:48
【问题描述】:
我是 Prolog 的新手,我只是在想为什么这条规则在一个为真之后给我一个错误的结果。
likes(1,banana).likes(1,mango).
test :- likes(1,banana),likes(1,mango).
?- test.
true;
false.
我想知道这个错误背后的原因。
【问题讨论】:
我是 Prolog 的新手,我只是在想为什么这条规则在一个为真之后给我一个错误的结果。
likes(1,banana).likes(1,mango).
test :- likes(1,banana),likes(1,mango).
?- test.
true;
false.
我想知道这个错误背后的原因。
【问题讨论】:
prolog 的工作方式是评估查询,直到否定失败。
在这里,您已经确定了两个事实:
likes(1, banana). 上面写着“1 喜欢香蕉”
likes(1, mango). 上面写着“1 喜欢芒果”
那么你已经建立了一个规则,它基本上评估为:
left_hand_side :- right_hand_side.left_hand_side 如果 right_hand_side
作为查询的规则评估尝试匹配事实,如果可以则返回true,如果无法匹配则返回false。需要注意的一件重要事情是,如果指定,prolog 将继续匹配事实,只要规则评估为 true。
那么让我们逐步了解test :- likes(1,banana),likes(1,mango).
如果test 作为查询运行,prolog 首先尝试likes(1,banana),这是先前确定的事实,并且是真的。然后,它转到likes(1,mango),这又是一个事实,而且是真的。然后 Prolog 到达规则的末尾,并输出 true。
此时,如果您不是在搜索更多匹配项,您可以缩短查询,只使用 true。但是,如果您要查找更多(所有)匹配项,请启动 回溯 并尝试再次评估规则,以搜索更多匹配项。
但是,由于您的规则只匹配“喜欢香蕉和喜欢芒果”并且我们已经匹配了likes(1,banana),当prolog 回溯并尝试再次评估likes(1,banana) 时,因为我们之前已经匹配了它,所以这次没有另一个事实上(换句话说, 1 不能多次“喜欢”香蕉,除非已经定义)来匹配。这就是false 的来源。
在您的 prolog 解释器中,您可以通过键入 trace. 然后运行您的查询来跟踪程序的执行。我的踪迹如下:
| ?- trace
.
The debugger will first creep -- showing everything (trace)
(1 ms) yes
{trace}
| ?- test.
1 1 Call: test ?
2 2 Call: likes(1,banana) ?
2 2 Exit: likes(1,banana) ?
3 2 Call: likes(1,mango) ?
3 2 Exit: likes(1,mango) ?
1 1 Exit: test ?
true ? ;
1 1 Redo: test ?
2 2 Redo: likes(1,banana) ?
2 2 Fail: likes(1,banana) ?
1 1 Fail: test ?
(1 ms) no
{trace}
| ?-
最后要注意的一件事:如果我没有在true ? 提示符下按;,而是按<ENTER>,则脚本将仅使用true 完成。
很高兴你问了这个问题,因为它让我对 prolog 有一点点复习,我真的很喜欢,但很长时间没有用过。
【讨论】:
like(1,X). 这样的变量时才会进行回溯,但现在我对这个概念更加清楚了。再次感谢。