Prolog - 参数没有充分实例化

时间:2014-05-22 19:54:17

标签: prolog arguments 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).  

如果我执行这样的代码:

?- not_number([1,2,3,5], R).

我得到R = 0(应该是)

R = 0.

但是如果我在列表中添加一个字符:

?- not_number([1,2,3,5,a], R).

然后我收到了这个错误:

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

有人可以解释代码有什么问题吗?我是prolog的新手。

4 个答案:

答案 0 :(得分:16)

我正在写这个答案,因为最好的答案是comment lurker。我想让它显示为一个真正的答案。

您的代码无效,因为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. 。你的递归案件有点倒退。你想这样做:

is

现在cmd = 'java -jar ' + args process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 的右侧在被调用时被实例化。

答案 1 :(得分:4)

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

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).

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

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

Prolog,如果有机会,将通过所有可能的路线。如果您这样做:

cat(adam).
cat(eve).

然后问:

?- cat(X).

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

not_number([_|Tail],Result):-
    not_number(Tail,Result).  

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

number(Head).

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

要强制Prolog查找其他一些结果,您必须按“;”在键盘上(就像在adam和eve示例中一样)。

答案 2 :(得分:0)

此类问题的一般解决方案是使用约束

例如,如果您只使用约束,您的程序将完全按预期工作。只需将(is)/2替换为(#=)/2即可获得在所有方向上的整数算术

:- use_module(library(clpfd)).

not_number([],0).
not_number([X|T],R):- 
    \+ number(X),
    R1 #= R+1,  
    not_number(T,R1). 

not_number([_|Tail],Result):-
    not_number(Tail,Result).

示例查询及其结果:

?- not_number([1,2,3,5], R).
R = 0.

另请注意,我已将代码更改为使用ISO谓词(\+)/1而非not/1

答案 3 :(得分:0)

就我而言,我不得不使用is

而不是=

代替这个

X is AnotherVariable

我不得不写

X = AnotherVariable