为什么在返回预期答案后,以下内容会以ERROR: Out of global stack
退出?
?- L #>= 0, L #=< 3, length(X, L).
L = 0,
X = [] ;
L = 1,
X = [_G1784] ;
L = 2,
X = [_G1784, _G1787] ;
L = 3,
X = [_G1784, _G1787, _G1790] ;
ERROR: Out of global stack
更新:W.r.t。 @ Joan的回答,我试图理解为什么它没有终止,不一定找到 终止的解决方案。我的意思是,如果问题是无约束力,那么在贴标签之前它不应该同样产生任何答案,对吧?所以我的问题与产生答案(而不是终止)的机制有关,而不是修复代码。
答案 0 :(得分:5)
问题是长度/ 2谓词是坚定的。您可以找到一些帖子来了解Stack Overflow中的坚定性,@mat的一个好问题是:Steadfastness: Definition and its relation to logical purity and termination。简单来说,坚定性是谓词最后评估它的参数的属性。
在您的示例中,您可以给出约束:
L #>= 0, L #=< 3
但在length(X, L).
L中将在最后评估。所以会发生的是length(X, L)
有无限的选择点(它会检查每个列表X),对于每个列表X,它将评估L,如果L符合约束,那么它将返回给你一个答案并继续检查导致无限循环的下一个列表。
您可以在跟踪模式中看到以下内容:
Call: (8) length(_G427, _G438) ? creep
Exit: (8) length([], 0) ? creep
Call: (8) integer(0) ? creep
Exit: (8) integer(0) ? creep
Call: (8) 0>=0 ? creep
Exit: (8) 0>=0 ? creep
Call: (8) integer(0) ? creep
Exit: (8) integer(0) ? creep
Call: (8) 3>=0 ? creep
Exit: (8) 3>=0 ? creep
X = [],
L = 0 ;
Redo: (8) length(_G427, _G438) ? creep
Exit: (8) length([_G1110], 1) ? creep
Call: (8) integer(1) ? creep
Exit: (8) integer(1) ? creep
Call: (8) 1>=0 ? creep
Exit: (8) 1>=0 ? creep
Call: (8) integer(1) ? creep
Exit: (8) integer(1) ? creep
Call: (8) 3>=1 ? creep
Exit: (8) 3>=1 ? creep
X = [_G1110],
L = 1 ;
Redo: (8) length([_G1110|_G1111], _G438) ? creep
Exit: (8) length([_G1110, _G1116], 2) ? creep
Call: (8) integer(2) ? creep
Exit: (8) integer(2) ? creep
Call: (8) 2>=0 ? creep
Exit: (8) 2>=0 ? creep
Call: (8) integer(2) ? creep
Exit: (8) integer(2) ? creep
Call: (8) 3>=2 ? creep
Exit: (8) 3>=2 ? creep
X = [_G1110, _G1116],
L = 2 ;
Redo: (8) length([_G1110, _G1116|_G1117], _G438) ? creep
Exit: (8) length([_G1110, _G1116, _G1122], 3) ? creep
Call: (8) integer(3) ? creep
Exit: (8) integer(3) ? creep
Call: (8) 3>=0 ? creep
Exit: (8) 3>=0 ? creep
Call: (8) integer(3) ? creep
Exit: (8) integer(3) ? creep
Call: (8) 3>=3 ? creep
Exit: (8) 3>=3 ? creep
X = [_G1110, _G1116, _G1122],
L = 3 ;
Redo: (8) length([_G1110, _G1116, _G1122|_G1123], _G438) ? creep
Exit: (8) length([_G1110, _G1116, _G1122, _G1128], 4) ? creep
Call: (8) integer(4) ? creep
Exit: (8) integer(4) ? creep
Call: (8) 4>=0 ? creep
Exit: (8) 4>=0 ? creep
Call: (8) integer(4) ? creep
Exit: (8) integer(4) ? creep
Call: (8) 3>=4 ? creep
Fail: (8) 3>=4 ? creep
正如您在第一次调用length([_G1110|_G1111], _G438)
中所看到的那样,它不会从头开始计算L,但它会根据第一个参数计算它,然后检查约束。
答案 1 :(得分:2)
这只是因为当长度运行时,它仍然只是一个未绑定的变量。它直到:
该变量将绑定到单个值。
您可以通过执行以下操作来修复您的示例:
?- L #>= 0, L #=< 3, label([L]), length(X, L).
要查看第一点,您可以看到:
?- L #>= 1, L #=< 1, length(X, L).
也有效,因为变量被约束为单个值。