Prolog 语句从不统一
Prolog statement never unifies
我有 3 个递归规则,但其中一个从未与我的查询统一。
checkCollisionDiagonal(QueenTarget,[],Qdist,0).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
abs(QueenTarget - Q) =\= Qdist,
NextQdist is Qdist + 1,
checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
abs(QueenTarget - Q) = Qdist,
NextQdist is Qdist + 1,
checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X1),
X is X1+1.
绝对值与Qdist不同的语句工作正常,如果它不统一我的程序应该检查下一条语句(绝对值等于Qdist的语句),但是使用trace我注意到第二个永远不会评估语句 (abs = Qdist)。为什么会这样?
我的查询是 checkCollisionDiagonal(1, [2,1,4,1], 1, X).
,预期结果应该是 2,但它总是 returns false
确实统一了,统一不是你想要的:
?- abs(5 - 2) = Qdist.
Qdist = abs(5-2)
它们不是函数,abs() 不做任何计算。换个词就更清楚了:
?- szz(5 $ / * foo) = Qdist.
Qdist = szz(5$(/)*foo)
变量 Qdist 与该项统一。
你需要 =:=
、=\=
或 is
,它们都知道如何计算 abs(5 - 2)
:
Qdist is abs(5 - 2)
将右侧计算为算术表达式 (abs(5 - 2)
) 并将结果与 Qdist
.
统一
Qdist =:= abs(5 - 2)
将两边作为算术表达式求值,比较结果,相等则成功。
Qdist =\= abs(5 - 2)
是=:=/2
的否定:将两边都作为算术表达式求值,比较结果,不相等则成功。
请参阅 arithmetic predicates 的文档。
为什么你的程序会失败?显然,您的程序(无论出于何种原因)过于专业化。因此,让我们概括您的程序,使其仍然失败但至少要小一些。为此,让我们使用 *
删除目标,从而概括程序。您的查询也可以通过用简单的下划线替换子列表 [1,4,1]
来概括。
:- op(950, fy, *).
* _. % the goal is just true instead
checkCollisionDiagonal(_QueenTarget,[],_Qdist,0).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
abs(QueenTarget - Q) =\= Qdist,
* NextQdist is Qdist + 1,
* checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
abs(QueenTarget - Q) = Qdist,
* NextQdist is Qdist + 1,
* checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X1),
* X is X1+1.
?- checkCollisionDiagonal(1, [2|_/*,1,4,1*/], 1, X) ).
false.
因为这个通用程序失败了,你原来的程序也失败了。所以现在你有一个更小的部分来找到有问题的错误(已经被另一个答案给出了)。
我有 3 个递归规则,但其中一个从未与我的查询统一。
checkCollisionDiagonal(QueenTarget,[],Qdist,0).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
abs(QueenTarget - Q) =\= Qdist,
NextQdist is Qdist + 1,
checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X).
checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):-
abs(QueenTarget - Q) = Qdist,
NextQdist is Qdist + 1,
checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X1),
X is X1+1.
绝对值与Qdist不同的语句工作正常,如果它不统一我的程序应该检查下一条语句(绝对值等于Qdist的语句),但是使用trace我注意到第二个永远不会评估语句 (abs = Qdist)。为什么会这样?
我的查询是 checkCollisionDiagonal(1, [2,1,4,1], 1, X).
,预期结果应该是 2,但它总是 returns false
确实统一了,统一不是你想要的:
?- abs(5 - 2) = Qdist.
Qdist = abs(5-2)
它们不是函数,abs() 不做任何计算。换个词就更清楚了:
?- szz(5 $ / * foo) = Qdist.
Qdist = szz(5$(/)*foo)
变量 Qdist 与该项统一。
你需要 =:=
、=\=
或 is
,它们都知道如何计算 abs(5 - 2)
:
统一Qdist is abs(5 - 2)
将右侧计算为算术表达式 (abs(5 - 2)
) 并将结果与Qdist
.Qdist =:= abs(5 - 2)
将两边作为算术表达式求值,比较结果,相等则成功。Qdist =\= abs(5 - 2)
是=:=/2
的否定:将两边都作为算术表达式求值,比较结果,不相等则成功。
请参阅 arithmetic predicates 的文档。
为什么你的程序会失败?显然,您的程序(无论出于何种原因)过于专业化。因此,让我们概括您的程序,使其仍然失败但至少要小一些。为此,让我们使用 *
删除目标,从而概括程序。您的查询也可以通过用简单的下划线替换子列表 [1,4,1]
来概括。
:- op(950, fy, *). * _. % the goal is just true instead checkCollisionDiagonal(_QueenTarget,[],_Qdist,0). checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):- abs(QueenTarget - Q) =\= Qdist, *NextQdist is Qdist + 1, *checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X). checkCollisionDiagonal(QueenTarget, [Q|QueenList], Qdist, X):- abs(QueenTarget - Q) = Qdist, *NextQdist is Qdist + 1, *checkCollisionDiagonal(QueenTarget, QueenList, NextQdist, X1), *X is X1+1. ?- checkCollisionDiagonal(1, [2|_/*,1,4,1*/], 1, X) ). false.
因为这个通用程序失败了,你原来的程序也失败了。所以现在你有一个更小的部分来找到有问题的错误(已经被另一个答案给出了)。