我正在尝试编写一个规则来决定一个项目是否X
恰好出现在列表中L
.
unique(X, [X|T]):- !, \+ member(X, T).
unique(X, [_|T]):- unique(X, T).
Run Code Online (Sandbox Code Playgroud)
该规则适用于确定值是否在列表中是唯一的,或者当我尝试使用unique(X, [1,2,3,1,3,2,5,4,3,8]).
它在列表中获取唯一值时返回正如false.
我所期望的那样(如member(X, list).
:
X = 5 ;
X = 4 ;
X = 8 ;
Run Code Online (Sandbox Code Playgroud)
我是一个完全的初学者,我不知道我做错了什么.
你一直在使用削减和不安全的否定形式.两者都必须非常谨慎地使用.立即解决方法是保护您的程序免受不适用于以下情况的用途:
unique(X, Xs) :-
iwhen(ground(X+Xs), your_unique(X, Xs)).
Run Code Online (Sandbox Code Playgroud)
这使用iwhen/2
类似于when/2
它不会延迟:
:- meta_predicate iwhen(+, 0).
iwhen(Cond, G_0) :-
when(Cond, ( Called = true, G_0 ) ),
( var(Called) -> throw(error(instantiation_error,_)) ; true ).
Run Code Online (Sandbox Code Playgroud)
以上适用于系统提供when/2
.以下是适用于任何ISO标准的系统:
iwhen(Cond, G_0) :-
( when_condition(Cond)
-> ( Cond -> G_0 ; throw(error(instantiation_error,_)) )
; throw(error(domain_error(when_condition, Cond),_))
).
when_condition(C) :-
var(C),
!,
throw(error(instantiation_error,_)).
when_condition(ground(_)).
when_condition(nonvar(_)).
when_condition(?=(_, _)).
when_condition(( A, B )) :-
when_condition(A),
when_condition(B).
when_condition(( A ; B )) :-
when_condition(A),
when_condition(B).
Run Code Online (Sandbox Code Playgroud)
另一方面,它总是非常令人沮丧地接收实例化错误,而不是真正的答案.所以,让我们的程序真的很纯粹!
你的第二条规则
unique(X, [_|Es]) :-
unique(X, Es).
Run Code Online (Sandbox Code Playgroud)
以声明方式,从右到左(即:-
一个?
)
提供
X
列表的唯一元素Es
,然后X
是列表的唯一元素[_|Es]
.
换句话说:每当我知道它X
是独一无二的时候Es
,它对于任何进一步的元素也是独一无二的Es
.这个结论不正确,考虑扩展名单X
!你需要一些额外的条件.此外,您的第一条规则需要重新制定.这用于non_member/2
:
unique(X, [X|Es]) :-
non_member(X, Es).
unique(X, [E|Es]) :-
dif(X, E),
unique(X, Es).
Run Code Online (Sandbox Code Playgroud)
这是另一种使用方式tfilter/3
:
unique(X, Es) :-
tfilter(=(X), Es, [_]).
Run Code Online (Sandbox Code Playgroud)
最有效的可能是它使用以下if_/3
的library(reif)
:
unique(X, [E|Es]) :-
if_(X = E, non_member(E, Es), unique(X, Es) ).
Run Code Online (Sandbox Code Playgroud)
这是一个简单的解决方案,使用nth0/4
(或select/3
如@false指出的):
unique(X, L) :-
nth0(_, L, X, R),
\+ member(X, R).
Run Code Online (Sandbox Code Playgroud)
nth0/4
第四个参数是删除了元素的R
列表。我们只需检查它不在 中。L
X
X
R
unique(X, L) :-
nth0(_, L, X, R),
maplist(dif(X), R).
Run Code Online (Sandbox Code Playgroud)
这解决了@false 指出的问题,但由于您是初学者,我怀疑您对此是否感兴趣。
这样做的优点是在这样的情况下工作:
?- unique(b, [X, Y, a]).
X = b,
dif(Y, b) ;
Y = b,
dif(X, b) ;
false.
Run Code Online (Sandbox Code Playgroud)