List SICStus Prolog列表

List SICStus Prolog列表,list,prolog,prolog-lists,List,Prolog,Prolog Lists,理解Prolog如何工作有困难。我正在尝试编写一个规则,将三个整数列表作为输入(表示集合),并将属于第一个和第二个列表的整数放入第三个列表 例如: ?-inter([10,20,30,40],[10,50,40,60], List3 ) List3 = [10, 40] 到目前为止,我有一个,可以识别列表是否包含某个字母: mymember(X,[X|T]). mymember(X,[H|T]) :- mymember(X,T). 实际上,有一个内置的库可以为您整理这些内容,称为ordset

理解Prolog如何工作有困难。我正在尝试编写一个规则,将三个整数列表作为输入(表示集合),并将属于第一个和第二个列表的整数放入第三个列表

例如:

?-inter([10,20,30,40],[10,50,40,60], List3 )
List3 = [10, 40]
到目前为止,我有一个,可以识别列表是否包含某个字母:

mymember(X,[X|T]).
mymember(X,[H|T]) :- mymember(X,T).

实际上,有一个内置的库可以为您整理这些内容,称为ordsets

inter(X, Y, Z) :-
    list_to_ord_set(X, L1),
    list_to_ord_set(Y, L2),
    ord_intersection(L1, L2, Z).
使用示例输入,您可以得到以下结果

| ?- inter([10,20,30,40],[10,50,40,60],X).
X = [10,40] ? ;
no
inter(Xs,Ys,Zs)
将在Zs中的每个元素也在Xs和Ys中时为真

但Z是未知的,因此需要更具建设性的方法。 这里是:
在Xs上迭代,并将Ys中的每个元素存储在Zs中

迭代的一个例子是mymember/2,您可以看到它需要一个递归谓词。 上面语句的另一个惯用部分是
存储在Zs
,Prolog有一种特殊的方法来做这些事情,使用模式匹配

inter([X|Xs], Ys, [X|Zs]) :-
   mymember(X, Ys), inter(Xs, Ys, Zs).

您将需要使用其他2个子句来完成inter/3:基本递归,即当所有Xs元素都已被处理时,以及当X不是Ys的成员时。

使用内置的
member/2
setof\3
尝试类似的操作:

set_intersection( As , Bs , Xs ) :-
  set_of( X , ( member(X,As) , member(X,Bs) ) , Xs )
  .
需要注意的是,如果列表
As
Bs
没有共同元素,则此操作将失败。另一种选择是使用
findall/3
而不是
set\u/3
findall/3
如果目标未实现,将返回并清空列表,而不是失败:

set_intersection( As , Bs , Xs ) :-
  findall( X , ( member(X,As) , member(X,Bs) ) , Xs )
  .
但是
findall/3
返回一个包(允许重复)而不是一个集合(不允许重复),因此如果您的两个源列表不是集合,您将无法获得集合

member/2
是一个内置谓词,它将其第一个参数与列表中的一个元素(相当于

member(X,[X|_).
member(X,[_|Xs) :- member(X,Xs) .
最后,@chac在他的回答中指出,您可以递归遍历列表

set_intersection( [] , _ , [] ) .            % the intersection of the empty set with anything is the empty set.
set_intersection( [A|As] , Bs , [A|Xs] ) :-  % if the list is non-empty,
  member(A,Bs) ,                             % - and A is a member of the 2nd set
  ! ,                                        % - we cut off alternatives at this point (deterministic)
  set_intersection( As , Bs , Xs )           % - and recurse down on the tail of the list.
  .
set_intersection( [_|As] , Bs , Xs ) :-      % if the list is non-empty, and A is NOT a embmer of the 2nd set
  set_intersection( As , Bs , Xs )           % we just recurse down on the tail of the list.
  .
@chac的技术在运行时构建结果列表,类似于:

[a|X]
[a,b|X]
[a,b,c|X]
最终的统一,即空列表的特例,将列表的未绑定尾部统一为使列表完整的
[]
,因此最终的
[a,b,c | X]

[a,b,c]
一点开场白的魔力。另一种可能更容易理解的方法是将辅助谓词与累加器一起使用:

%
% set_intersection/3: the public interface predicate
%
set_intersection( As , Bs , Xs ) :-
   set_intersection( As , Bc , [] , T ) % we seed our accumulator with the empty list here
   .


%
% set_intersection/4: the private worker bee predicate
%    
set_intersection( []     , _  , T , Xs ) :-   % since our accumulator is essentially a stack
  reverse(T,Xs)                               % we need to reverse the accumulator to 
  .                                           % put things in the expected sequence
 set_intersection( [A|As] , Bs , T  , Xs ) :-
  member( A, Bs ) ,
  ! ,
  T1 = [A|T] ,
  set_intersection( As , Bs , T1 , Xs )
  .
set_intersection( [_|As] , Bs , T , Xs ) :-
  set_intersection( As , Bs , T , Xs )
  .

你载入图书馆了吗?使用_模块(库(ordset))加载它