为清楚起见,感叹号是剪切运算符,它不表现为“句号”。它只是将您提交给在运行之前所做的选择。通过跟踪我们可以看到它实际上与您遇到的问题无关:
?- getNo(a,[[a,2],[b,1]],X).
X = 2 ; [trace]
Redo: (6) getNo(a, [[a, 2], [b, 1]], _G221) ? creep
Call: (7) getNo(a, [[b, 1]], _G221) ? creep
Call: (8) getNo(a, [], _G221) ? creep
Exit: (8) getNo(a, [], 0) ? creep
Exit: (7) getNo(a, [[b, 1]], 0) ? creep
Exit: (6) getNo(a, [[a, 2], [b, 1]], 0) ? creep
X = 0.
所以你可以在这里看到getNo(a, [], 0)
它也会成功。它也可以自己做,因为没有什么可以阻止它:
?- getNo(a,[],X).
X = 0.
没有理由期望它可以通过递归调用或仅通过使用 cut 的直接调用来区分到达空列表的情况。我认为你必须重组你的谓词以获得你想要的行为。例如:
get_number(A, [[A,X]|_], X).
get_number(A, [_|Tail], X) :- get_number(A, Tail, X).
getNo(A, L, X) :- get_number(A, L, X), !.
getNo(_, _, 0).
作为关于使用 Prolog 的附加说明,您经常需要创建另一个谓词。不要害怕创建辅助谓词。除此之外,没有其他方法可以真正处理需要设置初始条件或后处理的循环。在其他语言中,您可以将需要做的所有工作完全隔离在单个函数的接口后面,但在 Prolog 中,这通常是不可能的,您必须委托给助手。