我试着在Prolog中编写functor。这是我的版本:
lenlist(L,N) :- lenlist(L,0,N).
lenlist([],N,N).
lenlist([_|T],P,N) :- P1 is P+1 , lenlist(T,P1,N).
functor1(Term,F,N) :- Term =.. [F|Args] , lenlist(Args,N).
以下是Prolog内置函子的示例执行
?- functor(Term,f,6).
Term = f(_G247, _G248, _G249, _G250, _G251, _G252)
现在,如果我使用functor1
执行相同的查询,我会收到异常
?- functor1(Term,f,6).
ERROR: =../2: Arguments are not sufficiently instantiated
Exception: (8) _G180=..[f|_G248] ? creep
我写的functor1
函数有什么问题?
答案 0 :(得分:4)
starblue 是正确的,但为了正确编写您的functor1/3
版本,我建议您考虑所需的“模式”:
考虑到这三个案例,请尝试以下方法。首先,情况(1):从现有术语中提取Functor和Arity:
functor1(Term, Functor, Arity) :-
\+ var(Term), !,
% inspect existing term
Term =.. [Functor|ArgList],
length(ArgList, Arity).
请注意,如果Term参数不是带cut(!)的变量,我们会排除其他情况。其次,案例(2):构建一个来自Functor和Arity的术语:
functor1(Term, Functor, Arity) :-
var(Term),
atom(Functor),
number(Arity), !,
% build a term
length(ArgList, Arity),
Term =.. [Functor|ArgList].
请注意,切换前的子目标执行的模式检查(!)封装了此情况下的保护(前置条件)。最后,所有其他情况(即我们需要构建一个术语,但没有仿函数,或者任何一个)的情况都是无效的(3):
functor1(_Term, _Functor, _Arity) :-
throw('Arguments are not sufficiently instantiated.').
或者,对于最后一种情况,可以省略整个子句,以实现functor/1
为其将覆盖的其余参数绑定返回false的行为。
另请注意,此版本依赖于SWI-PROLOG中存在的内置插件length/2
,var/1
,number/1
和atom/1
(以及其他内容)。< / p>
答案 1 :(得分:2)
问题是Args尚未实例化= ..尝试将lenlist / 3放在它之前。
顺便说一下,你也可以使用内置长度/ 2。