Prolog - 参数没有充分实例化

Edd*_*his 18 arguments prolog clpfd instantiation-error

我正在写一个小程序,它计算列表中有多少元素不是数字.这是我的代码:

not_number([],0).
not_number([X|T],R):- 
    not(number(X)),
    R1 is R+1,  
    not_number(T,R1). 

not_number([_|Tail],Result):-
    not_number(Tail,Result).  
Run Code Online (Sandbox Code Playgroud)

如果我执行这样的代码:

?- not_number([1,2,3,5], R).
Run Code Online (Sandbox Code Playgroud)

我得到R = 0(应该是)

R = 0.
Run Code Online (Sandbox Code Playgroud)

但是,如果我在列表中放置一个字符:

?- not_number([1,2,3,5,a], R).
Run Code Online (Sandbox Code Playgroud)

然后我收到这个错误:

ERROR: not_number/2: Arguments are not sufficiently instantiated
   Exception: (10) not_number([a], _G247) ? 
Run Code Online (Sandbox Code Playgroud)

有人能解释代码有什么问题吗?我是prolog的新手.

小智 18

我正在写这个答案,因为最好的答案还在于潜伏者评论.我想让它显示为一个真正的答案.

您的代码不工作,因为你正在做R1 is R+1的时候R的情况不是实例not_number([X|T], R).你的递归案件有点倒退.你想这样做:

not_number([X|T],R):- 
    not(number(X)),
    not_number(T,R1),
    R is R1+1.
Run Code Online (Sandbox Code Playgroud)

现在,在is调用它时,实例化了它的右侧.


Dar*_*lar 6

你的问题是在这样的算术计算中:

A是B

右侧 (B) 的所有内容都必须已知。那里没有变量。

你可以这样做:

not_number(X, Y) :- not_number(X, Y, 0).
not_number([], Y, Y).
not_number([H|T], Y, Z) :-
    \+ (number(H)), 
    Z1 is Z+1,
    not_number(T, Y, Z1).

not_number([H|T], Y, Z) :-
    number(H),
    not_number(T, Y, Z).
Run Code Online (Sandbox Code Playgroud)

(现在测试了这段代码,它有效)。

现在第三个参数是一个累加器。它计算有多少个非数字。当列表为空时,第三个参数与第二个参数统一,成为正确的答案。

如果有机会,Prolog 将遍历所有可能的路径。如果你这样做:

cat(adam).
cat(eve).
Run Code Online (Sandbox Code Playgroud)

然后问:

?- cat(X).
Run Code Online (Sandbox Code Playgroud)

您可以获得两个答案:X = 亚当,X = 夏娃。它也适用于您的代码:请注意,当列表的头部不是数字时,您仍然可以执行以下操作:

not_number([_|Tail],Result):-
    not_number(Tail,Result).  
Run Code Online (Sandbox Code Playgroud)

这没有给出您想要的答案。你必须切断你不感兴趣的路线。在这种情况下,我会添加

number(Head).
Run Code Online (Sandbox Code Playgroud)

确保仅当该元素不是数字时我们才跳过列表中的元素而不将计数器增加 1。

要强制 Prolog 查找其他结果,您必须按“;” 在你的键盘上(就像亚当和夏娃的例子)。