我正在写一个Prolog谓词,从编号列表中删除前三个元素并打印结果 . 编号列表的示例:
[e(f,1),e(o,2),e(o,3),e(b,4),e(a,5),e(r,6)].
普通列表的原始谓词如下所示:
strim([H|T],R) :-
append(P,R,[H|T]),
length(P,3).
因此,由于长度谓词也适用于编号列表,我只需要编写谓词,将一个编号列表附加到另一个:
compose([],L,[L]).
compose([e(F,C)|T],e(A,_),[e(F,C)|L]) :-
N is C+1,
compose(T,e(A,N),L).
napp(X,[],X).
napp(L,[e(X,Y)|T],M):-
compose(L,e(X,Y),L1),
napp(L1,T,M).
我希望编号列表的谓词是普通列表的谓词的略微修改版本,所以我写了这样的:
numstrim([e(X,Y)|T],R) :-
napp(P,R,[e(X,Y)|T]),
length(P,3).
但是,我收到此错误:
ERROR: compose/3: Arguments are not sufficiently instantiated
有人可以解释导致错误的原因以及如何避免错误吗?我是Prolog的新手 .
1 回答
实例化错误是使用 moded 谓词的Prolog程序中的常见现象:这些谓词只能在特殊情况下使用,例如需要一些参数完全实例化等 .
作为初学者,我认为你建议使用 more general predicates 代替,这样你就可以自由地交换目标的顺序而不必考虑程序限制,至少不是那么早,并且没有自由实验的能力用你的代码 .
例如,在您的情况下,对
compose/3
进行以下微不足道的更改会为您提供一个适用于所有方向的谓词:在这里,我简单地用 CLP(FD) constraint
(#=)/2
替换了模式谓词(is)/2
,其中,completeley包含了比整数更低级别的谓词 .在这个小的改变之后(取决于您的Prolog系统,您可能必须导入库以使用更通用的算术谓词),我们得到:
因此,我们发现实例化错误实际上掩盖了一个不同的问题,这个问题只能在程序上理解,现在已经浮出水面 .
为了改善这一点,我现在转过
numstrim/2
的两个目标:这是因为
length(P, 3)
always terminates ,并且放置始终首先终止的目标最多可以改善,而不会恶化纯粹和单调逻辑程序的终止属性 .所以现在我们得到:
也就是说,至少我们现在得到答案!
但是,谓词仍然没有终止 universally ,因为我们得到:
我把这个作为一个练习 .