题
我是 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,如果不能匹配则为 false。需要注意的一件重要事情是,如果指定,只要规则评估为,序言将继续匹配事实 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
来自。
在您的序言解释器中,您可以通过输入来跟踪程序的执行 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
.
我很高兴你问这个问题,因为它让我对序言有了一点小小的回顾,我真的很喜欢它,但已经很长时间没有使用了。