您的 Pred 包含未绑定的变量。在第一次迭代中调用 Pred 时,这些变量绑定到第一个可能的值。在您的递归步骤中,Pred 已经有绑定变量,它们不能更改值。所以......这个解决方案将不起作用。
来自 SWI-Prolog 的跟踪(由于某些原因,我不得不将 new/2 重命名为 item/2):
第一级(调用:my_findall(A,B,member(p(A,B), [p(1,2), p(3,4)]), L). )。
Call: (7) my_findall(_G819, _G820, member(p(_G819, _G820), [p(1, 2), p(3, 4)]), _G840) ? creep
Call: (8) lists:member(p(_G819, _G820), [p(1, 2), p(3, 4)]) ? creep
Exit: (8) lists:member(p(1, 2), [p(1, 2), p(3, 4)]) ? creep
我们得到 p(A,B) = p(1,2)。此时 A 绑定为 1,B 绑定为 2。
^ Call: (8) not(item(1, 2)) ? creep
Call: (9) item(1, 2) ? creep
Fail: (9) item(1, 2) ? creep
^ Exit: (8) not(item(1, 2)) ? creep
好的,数据库中没有 item(1,2)。
^ Call: (8) assert(item(1, 2)) ? creep
^ Exit: (8) assert(item(1, 2)) ? creep
现在 item(1,2) 为真。递归调用:
Call: (8) my_findall(_L215, _L216, member(p(1, 2), [p(1, 2), p(3, 4)]), _L199) ? creep
让我们用另一个解决方案做 Pred:
Call: (9) lists:member(p(1, 2), [p(1, 2), p(3, 4)]) ? creep
^^^^^^^
看到下划线的部分了吗?
要使这项技术发挥作用,您可能应该复制 Pred,递归地将 N 和 P 更改为新变量。对于每次迭代,您必须“创建”新的 N 和 P 对。检查 copy_term/2 ( http://www.swi-prolog.org/pldoc/doc_for?object=copy_term%2f2 )。