我试图输出仅包含唯一元素的列表。但是结果并不完美。
list_concatenation([],L,L).
list_concatenation([X1|L1],L2,[X1|L3]) :-
list_concatenation(L1,L2,L3).
list_member(X, [X|_]).
list_member(X, [_|TAIL]) :- list_member(X,TAIL),!.
toset([],_).
toset([X|TAIL],SET):-
list_member(X,SET),
toset(TAIL,SET).
toset([X|TAIL],SET):-
\+ list_member(X,SET),
list_concatenation([X],SET,NEWSET),
toset(TAIL,NEWSET).
例如:
?- toset([1,1,2,3],X).
结果应该是
'X = [1, 2, 3]'
,但现在是'X = [1, 2, 3|_16998]'
答案 0 :(得分:1)
您实际上以错误的方式实现了toset/2
。您实际上在这里使用list_member/2
将元素添加到列表中。确实,如果您使用自由变量,则会得到:
?- list_member(2, L).
L = [2|_3616] ;
L = [_3614, 2|_3622].
list_member/2
本身也没有正确实现。此处的剪切(!
阻止保持屈服值。因此,您应该删除剪切:
list_member(X, [X|_]).
list_member(X, [_|Tail]) :-
list_member(X,Tail).
因此,这可以产生其中2
是成员的所有可能的列表:
?- list_member(2, L).
L = [2|_3412] ;
L = [_3410, 2|_3418] ;
L = [_3410, _3416, 2|_3424] ;
L = [_3410, _3416, _3422, 2|_3430] ;
...
但是现在问题仍然存在:您不应该在此处使用list_member/2
将元素添加到列表中,可以在此处使用累加器来跟踪已经产生的元素,然后最终返回该累加器,例如:
toset(L, S) :-
toset(L, [], S).
toset([], A, S):-
reverse(A, S).
toset([H|T], A, L) :-
( member_list(H, A)
-> toset(T, [H|A], L)
; toset(T, A, L)
).
因此,我们将这些值始终放在累加器的前面,最后reverse/2
[swi-doc]累加器,然后将其返回。