Prolog代码中r(X)返回false时test2(X,Y)为何返回X=7,Y=8?
为什么
test2(X,Y)会返回X=7,Y=8? 嘿,这个问题的核心是你混淆了**“查询谓词的所有变量解”和“带着具体参数调用谓词是否成立”**这两种场景,再加上对Prolog截断(!)触发条件的小误解,咱们一步步拆解清楚:
先梳理test2(X,Y)的执行流程
test2(X,Y)的定义是:
test2(X,Y):- p(X,Y), r(Y).
它的执行逻辑是:先枚举p(X,Y)的所有事实,然后对每个Y值,检查r(Y)是否成立。我们先列出p/2的所有事实:
p(3,4)p(6,9)p(7,8)
现在逐个分析每个Y对应的r(Y)是否成立:
1. Y=4时
调用r(4),等价于s(4), t(4)。
s(4)没有匹配的子句,直接失败,所以这个分支被跳过。
2. Y=9时
调用r(9),等价于s(9), t(9)。
s(9)没有匹配的子句,失败,分支跳过。
3. Y=8时
调用r(8),等价于s(8), t(8),这就是关键所在:
先看s(8)的匹配过程
s/1的定义是:
s(7). s(6):-!. s(8).
当调用s(8)时,Prolog会从上到下匹配子句:
- 第一个子句
s(7):参数7≠8,不匹配; - 第二个子句
s(6):-!:参数6≠8,完全不匹配,这里截断!根本不会触发(截断只有在子句匹配成功时才会生效); - 第三个子句
s(8):参数完全匹配,直接成功!
再看t(8)的匹配过程
t/1的定义是:
t(9). t(8). t(5):-!. t(4).
调用t(8)时,第二个子句t(8)直接匹配成功,所以t(8)成立。
既然s(8)和t(8)都成立,那么r(8)自然成立!对应p(X,Y)的事实就是p(7,8),所以test2(X,Y)返回X=7,Y=8。
澄清你的误解
你提到“已知s(X)返回X=7;X=6,t(X)返回X=9;X=8;X=5”,这是直接查询s(X)和t(X)(变量X无约束)时的所有解,但在r(Y)的调用中,我们是带着具体的Y值(比如8)去调用s(Y)和t(Y),不是查询变量的所有解。这两种场景完全不同:
- 直接查
s(X)时,回溯到s(6)匹配成功后触发截断!,会阻止后续回溯到s(8),所以解只有7和6; - 但直接调用
s(8)时,s(6)的子句根本不匹配,截断没生效,所以s(8)可以正常匹配成功。
内容的提问来源于stack exchange,提问作者Ironwing
相关产品推荐
相关产品推荐

