问题描述
memberchk/2
是一个常用的谓词,它是根据 member/2
定义的,如下所示:
memberchk/2
is a commonly defined predicate that is defined in terms of member/2
like so:
memberchk(X, Xs) :-
once(member(X, Xs)).
因此它只对 member/2
的第一个答案成功.它的完整程序意义不适合纯粹的关系.作为其非关系行为的示例,请考虑
It therefore succeeds only for the first answer of member/2
. Its full procedural meaning does not fit into a pure relation. As an example for its non-relational behavior consider
?- memberchk(b, [X,b]), X = a.
false.
?- X = a, memberchk(b, [X,b]).
X = a.
另一方面,在许多情况下,memberchk/2
将使用 充分实例化 参数调用,在这种情况下,它可以被视为纯关系的有效近似.
On the other hand, in many cases memberchk/2
will be called with sufficiently instantiated arguments, where it can be seen as an efficient approximation of a pure relation.
一个这样的纯关系背后是 memberd/2
(使用 if_/3
):
One such pure relation behind is memberd/2
(using if_/3
):
memberd(E, [X|Xs]) :-
if_(E = X, true, memberd(E, Xs) ).
对于充分实例化的情况,是否有任何其他可以通过 memberchk/2
近似的纯关系?
Are there any other pure relations that can be approximated by memberchk/2
for sufficiently instantiated cases?
换句话说:memberd/2
是 memberchk/2
的完整声明式替代,还是仍然存在 memberchk/2
的合法情况> 不能用 memberd/2
代替吗?
In other words: Is memberd/2
a full, declarative replacement for memberchk/2
or are there still legitimate cases where memberchk/2
cannot be replaced by memberd/2
?
推荐答案
这里有一个众所周知的使用 member/2
的例子,它不能用 memberd/2
: bridge.pl
Pascal Van Hentenryck 给出的桥梁调度问题.
Here is a well-known example use of member/2
that cannot be represented by memberd/2
: bridge.pl
the bridge scheduling problem given by Pascal Van Hentenryck.
在设置阶段使用member/2
:
setup(K,Ende,Disj):-
jobs(L),
make_vars(L,K),
member([stop,_,Ende],K),
....
所以在这里,实际上三元素列表中的第一个元素用于选择特定任务,而 memberd/2
使用整个元素进行比较.因此,这个 setup/3
留下了很多选择点(实际上是 219 个).有些人(如 SICStus)在这种情况下使用 memberchk/2
,从而冒着非单调性的风险.
So here, effectively the first element in the three-element list is used to select a particular task whereas memberd/2
uses the entire element for comparison. As a consequence this setup/3
leaves open a lot of choicepoints (actually, 219). Some (like SICStus) use memberchk/2
in that situation, thereby risking non-monotonicity.
使用以下纯替换,可以避免所有选择点.
Using the following pure replacement, all choicepoints are avoided.
member3l([N,D,A], Plan) :-
tmember(l3_t(N,D,A), Plan).
l3_t(N,D,A, X, T) :-
X = [Ni|_],
if_(N = Ni, ( X=[N,D,A], T = true ), T = false ).
tmember(P_2, [X|Xs]) :-
if_( call(P_2, X), true, tmember(P_2, Xs) ).
或者使用 library(lambda)
:
member3li([N,Nd,Na], Plan) :-
tmember([N,Nd,Na]+X^T^
( X=[Nk|_],
if_( Nk = N, ( X=[N,Nd,Na], T = true ), T = false ) ),
Plan).
tmember/2
的其他用途:
old_member(X, Xs) :-
tmember( X+E^T^( X = E, T = true ; T = false ), Xs).
old_memberd(X, Xs) :-
tmember(=(X), Xs).
这是一个更紧凑的表示:
Here is a more compact representation:
member3l([N,D,A], Plan) :-
tmember({N,D,A}+[Ni,Di,Ai]^cond_t(N = Ni, [D,A] = [Di,Ai] ), Plan).
使用 library(lambda)
和
cond_t/3
:
cond_t(If_1, Then_0, T) :-
if_(If_1, ( Then_0, T = true ), T = false ).
这篇关于memberchk/2 的声明式使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!