【问题标题】:Open list and member打开列表和成员
【发布时间】:2016-06-07 10:28:33
【问题描述】:

由于我想避免append/3 的成本,我使用差异/开放列表。

然而,打开列表的问题是member/2 通过将元素添加到尾部来对打开列表做出反应。例如:

?- L=[a|_],member(b,L).
L = [a, b|_G1196] ;
L = [a, _G1195, b|_G1199] ;
L = [a, _G1195, _G1198, b|_G1202] ;
L = [a, _G1195, _G1198, _G1201, b|_G1205] ;
L = [a, _G1195, _G1198, _G1201, _G1204, b|_G1208] ;
L = [a, _G1195, _G1198, _G1201, _G1204, _G1207, b|_G1211] 

这是正确的行为,因为打开的列表有一个无限的“尾部”,member/2 函数将此尾部/孔(变量)与成员的第一个参数统一起来。

不过,我正在寻找一种方法来检查打开列表中是否有一个元素等于给定元素。我该怎么做?

【问题讨论】:

  • 请出示一些代码。

标签: prolog difference-lists


【解决方案1】:

你可以编写自己的member/2:member_open/2:

member_open(_,X) :-
    var(X),
    !,
    fail.
member_open(X,[X|_]).
member_open(X,[_|T]) :-
    member_open(X,T).

或更纯粹的方法:

member_open(X,Y) :-
    \+var(Y),
    Y = [X|_].
member_open(X,Y) :-
    \+var(Y),
    Y = [_|T],
    member_open(X,T).

谓词假设打开列表的尾部为var/1。如果谓词找到这样的尾部,它会执行切割 (!) 并失败。

演示

?- member_open(a,[]).
false.

?- member_open(a,[a]).
true ;
false.

?- member_open(a,[a,a]).
true ;
true ;
false.

?- member_open(a,[a,a|_]).
true ;
true ;
false.

?- member_open(b,[a,a|_]).
false.

?- member_open(X,[X,a|_]).
true ;
X = a ;
false.

?- member_open(X,[c,a|_]).
X = c ;
X = a ;
false.

【讨论】:

  • @Gilgamesz:一个问题是有no generally accepted definition。但由于它使用了切割,它可能不是。但是,您可以将其重写为“more purer”(引号之间)变体。虽然var 也可以被认为是非纯的......如果你的定义相当严格,我认为不可能实现这样的member_open/2 谓词。
  • 这绝对是 not 一个逻辑关系,例如:?- member(E, Ls). fails(声明式地,这意味着:有 no解决方案),但更具体查询成功,例如:?- member(E, [E|_]).。从纯逻辑关系来看,我们当然期望如果特定查询成功,那么更一般的查询不会失败
  • 问题本身甚至引用了它的逻辑版本:众所周知的member/2 谓词是完全纯正的iff元素是列表的成员。
  • 一个合乎逻辑的方法是简单地使用member/2。其他方式,如果您无法在当前时间点做出正确的决定,包括抛出instantiation_error,或使用约束来延迟决定。参见 freeze/2 以及 Ulrich Neumerkel 的 library(pio) 中如何使用它。看一个变量,只承诺“那个变量永远不会被实例化为某事”,这绝对是不纯的,只要你这样做,你就不能期望获得良好的关系。
  • member(E, Ls)的声明性含义是:E出现在列表Ls中。这绝对也适用于开放列表,具有完全相同的含义。因此,您可以使用member/2 来表达这一点。我认为你应该退后一步,重新考虑为什么你实际上首先使用开放列表。如果您只想避免append/3 的开销,只需前置 元素,例如使用Ls = [E|Ls0]。这是在 O(1).
猜你喜欢
  • 1970-01-01
  • 2014-03-07
  • 2021-05-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
相关资源
最近更新 更多