实现Prolog谓词,说明元素是否属于列表。没有数字列表的问题

时间:2013-04-07 17:05:18

标签: prolog prolog-dif

我正在学习Prolog的大学考试,我对这个练习有问题:

  

如果元素not_member(X,L)不属于列表X,则实现谓词L为真。

如果我的推理是正确的,我找到了一个解决方案:

% FACT (BASE CASE): It is TRUE that X is not in the list if the list is empty.
not_member(_,[]).

% RULE (GENERAL CASE): If the list is non-empty, I can divide it in its Head
%   element and the sublist Tail. X does not belong to the list if it is different 
%   from the current Head element and if it does not belong to the sublist Tail.
not_member(X,[Head|Tail]) :-
   X =\= Head,
   not_member(X,Tail).

此代码适用于数字列表,如以下查询所示:

2 ?- not_member(4, [1,2,3]).
true.

3 ?- not_member(1, [1,2,3]).
false.

但是,列表中包含一些非数字元素, 它不起作用并报告错误:

4 ?- not_member(a, [a,b,c]).
ERROR: =\=/2: Arithmetic: `a/0' is not a function

为什么?

2 个答案:

答案 0 :(得分:4)

让我们查看文档!

(=\=)/2是算术运算符。

  

+ Expr1 = \ = + Expr2       如果表达式Expr1的计算结果与Expr2不相等,则为真。

您必须使用(\=)/2来比较两个通用术语:

not_member(_, []) :- !.

not_member(X, [Head|Tail]) :-
     X \= Head,
    not_member(X, Tail).

?- not_member(d, [a,b,c]).
true.

答案 1 :(得分:2)

使用获取逻辑上合理的答案 -

in this answer一样,我们将non_member(E,Xs)定义为maplist(dif(E),Xs)

我们让maplist(dif(E),Xs)not_member(E,Xs) by @Haile参与测试!

?- not_member(E,[1,2,3]).
false.                                   % wrong! What about `E=4`?

?- maplist(dif(E),[1,2,3]).
dif(E,1), dif(E,2), dif(E,3).            % success with pending goals

坚定吗? (有关此重要问题的更多信息,请阅读 thisthisthisthis回答。)

?- E=d, not_member(E,[a,b,c]).
E = d.
?-      not_member(E,[a,b,c]), E=d.
false.                                  % not steadfast

?- E=d, maplist(dif(E),[a,b,c]).
E = d.
?-      maplist(dif(E),[a,b,c]), E=d.   % steadfast
E = d.

让我们不要忘记最常用的用途!

?- not_member(E,Xs).               
Xs = [].                                % a lot of solutions are missing!

?- maplist(dif(E),Xs).
  Xs = []
; Xs = [_A]      , dif(E,_A)
; Xs = [_A,_B]   , dif(E,_A), dif(E,_B)
; Xs = [_A,_B,_C], dif(E,_A), dif(E,_B), dif(E,_C)
...