删除SWI-Prolog中的元素或列表

Nol*_*ter 2 prolog

另一个问题,我有一个很好的工作"功能"删除:

remove([],X,[]) :- !. 
remove([X|T],X,L1) :- !, remove(T,X,L1).         
remove([H|T],X,[H|L1]) :- remove(T,X,L1). 
Run Code Online (Sandbox Code Playgroud)

但它不能像我希望它一样工作.它删除元素甚至列表......

...但不会删除所有外观.这是目标:

remove([A,B,[C],[A,[B]],[[A,[B]]]],[A,[B]],X).
X=[A,B,[C],[]]
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Ale*_*nik 5

如果你想删除所有外观,例如,要删除([1,2,3,1],1,X)计算X = [2,3]只需用第二个子句替换

 remove([X|T],X,L1) :- remove(T,X,L1), !.  
Run Code Online (Sandbox Code Playgroud)

但是,您似乎希望a)使用应保留为变量的变量,以及b)从子列表中删除列表.

我们将首先解决b)问题.

remove([],_,[]) :- !. 
remove(A,_,A) :- \+ (A = [_|_]), !.
remove([X|T],X,L1) :- remove(T,X,L1), !.        
remove([H|T],X,[G|L1]) :- remove(H,X,G), remove(T,X,L1).
Run Code Online (Sandbox Code Playgroud)

如您所见,我们在最后一个子句中添加第二个递归调用来处理内部列表.此外,我们必须添加一个特殊情况(第二个子句),因为第一个参数不一定是列表.

最后,要解决a)你需要使用Sterling和Shapiro的"冻结"/"融化"谓词.冻结用表达式#VAR(0),#VAR(1),...替换变量,而熔化则相反.熔化传统上称为melt_new

numvars('#VAR'(N),N,N1) :- N1 is N+1.
numvars(Term,N1,N2) :- nonvar(Term), functor(Term,_,N),
                          numvars(0,N,Term,N1,N2).

numvars(N,N,_,N1,N1).
numvars(I,N,Term,N1,N3) :- I<N, I1 is I+1,
          arg(I1,Term,Arg), numvars(Arg,N1,N2),
          numvars(I1,N,Term,N2,N3).

frz(A,B) :- frz(A,B,0).
frz(A,B,Min) :- copy_term(A,B), numvars(B,Min,_),!.


melt_new(A,B) :-
   melt(A,B,Dictionary), !.

melt('$VAR'(N),X,Dictionary) :-
    lookup(N,Dictionary,X).
melt(X,X,Dictionary) :-
    constant(X).
melt(X,Y,Dictionary) :-
    compound(X),
    functor(X,F,N),
    functor(Y,F,N),
    melt(N,X,Y,Dictionary).

melt(N,X,Y,Dictionary) :-
    N > 0, 
    arg(N,X,ArgX), 
    melt(ArgX,ArgY,Dictionary),
    arg(N,Y,ArgY), 
    N1 is N-1, 
    melt(N1,X,Y,Dictionary).
melt(0,X,Y,Dictionary).

/*  
    lookup(Key,Dictionary,Value) :-
    Dictionary contains the value indexed under Key.
    Dictionary is represented as an ordered binary tree.

*/

    lookup(Key,dict(Key,X,Left,Right),Value) :-
        !, X = Value.
    lookup(Key,dict(Key1,X,Left,Right),Value) :-
        Key < Key1 , lookup(Key,Left,Value).
    lookup(Key,dict(Key1,X,Left,Right),Value) :-
        Key > Key1, lookup(Key,Right,Value).
Run Code Online (Sandbox Code Playgroud)

顺便说一下,我真的推荐Sterling和Shapiro的书"Prolog的艺术".第15章讨论了熔化和冷冻.

  • 你得到的答案与无意识的统一有关.如上所定义的谓词删除将按预期的方式工作,仅用于(基础列表)列表(=没有变量的项).如果您想将它应用于非地面情况,首先需要将术语置于地面(冻结),然后调用remove/3,最后返回非地面情况(melt_new). (2认同)