SWI-Prolog中列表末尾的未实例化变量

时间:2017-01-21 17:49:56

标签: prolog

我编写了一个程序来对符号中的数字进行排序,但是它有效,但是在列表末尾给出了一个内存地址,它没有经过最后一次。为什么会这样?

separate([],[],[]).
separate([X],X,_):-number(X).
separate([X],_,X).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-separate(Y,Z,S).

咨询?- separate([3,a,b,4,5,c],X,Y).

我明白了:

X = [3, 4, 5|_G2592],
Y = [a, b, c] .

2 个答案:

答案 0 :(得分:2)

我建议

separate([],[],[]).

separate([H | T], [H | Tn], Ls) :-
  number(H),
  separate(T, Tn, Ls).

separate([H | T], Ln, [H | Ts]) :-
  \+ number(H),
  separate(T, Ln, Ts).

如果你有一个终结条款separate([],[],[])和一些普通条款separate([X|Y],[X|Z],S)separate([X|Y],Z,[X|S]),你不需要半终结条款separate([X],X,_)separate([X],_,X)和它们(具有未定义的值_)避免统一其中一个列表,并获得“内存地址”(非统一变量的标识符)。

如果你有一个带有number(X)的子句,另一个(替代)子句需要“not-number”检查(即\+ number(X)),否则两个子句对数字都是正确的,你可以乘以解决方案,数字列表中没有数字。

答案 1 :(得分:1)

那是因为你保持列表开放

separate([X],X,_):-number(X).
separate([X],_,X).

问题是:你实际上不需要写这些语句,你可以省略它们:

separate([],[],[]).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-separate(Y,Z,S).

这会有效但会返回多个结果,而除了第一个,其余都是错误的。你应该通过在最后一个句子中添加一个守卫来解决这个问题:

separate([],[],[]).
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S).
separate([X|Y],Z,[X|S]):-\+ number(X),separate(Y,Z,S).

\+的行为类似于"而不是"在某种意义上,如果Prolog无法与\+ number(X)匹配,number(X)将会成功。

最后要注意的是,你所看到的并不是一个真正的内存地址:它只是一个未经实例化的变量,尽管这当然是一个小问题。