Prolog 为什么会员/2没有立即返回

Prolog 为什么会员/2没有立即返回,prolog,Prolog,我需要一个谓词来判断元素是否在列表中。我试图使用member/2,但我注意到一个奇怪的行为 当我调用类似于member(1[1,2,3])的东西时,SWI prolog输出true,并等待我按enter键,然后执行终止。当元素不在列表中时,不会发生这种情况 我有两个问题: 为什么会这样 立即返回的member/2的代码是什么 为什么会这样 member/2的定义允许多次成功,即使找到了完全相同的解决方案。在您的列表中,所有元素都不同。但是考虑到最后两个额外的1的情况: ?- member(1,[

我需要一个谓词来判断元素是否在列表中。我试图使用member/2,但我注意到一个奇怪的行为

当我调用类似于
member(1[1,2,3])的东西时,
SWI prolog输出
true
,并等待我按enter键,然后执行终止。当元素不在列表中时,不会发生这种情况

我有两个问题:

  • 为什么会这样
  • 立即返回的member/2的代码是什么
  • 为什么会这样
  • member/2
    的定义允许多次成功,即使找到了完全相同的解决方案。在您的列表中,所有元素都不同。但是考虑到最后两个额外的1的情况:

    ?- member(1,[1,2,3,1,1]).
    true ;
    true ;
    true.
    
  • 立即返回的member/2的代码是什么
  • 这通常称为
    memberd/2

    ?- memberd(1,[1,2,3,1,1]).
    true.
    
    ?- memberd(X,[1,2,3,1,1]).
    X = 1 ;
    X = 2 ;
    X = 3 ;
    false.
    
    区别很容易理解<代码>成员/2基本上定义为:

    member(X, [X|_Xs]).
    member(E, [_X|Xs]) :-
       member(E, Xs).
    
    请注意,这两个条款并不相互排斥!这就是为什么即使已经找到解决方案,它也会搜索替代解决方案的原因。在规则中,
    E
    \ux
    可能是相同的

    通过确保
    E
    X
    在规则中不同,我们得到了
    memberd/2
    的第一个定义:

    memberd(X, [X|_Xs]).
    memberd(E, [X|Xs]) :-
       dif(E, X),
       memberd(E, Xs).
    
    由于此
    dif/2
    规则仅在当前元素与
    E
    不同时才被考虑。然而,这里缺少的是Prolog在得出它们不相交之前仍然需要考虑两者。

    完整的定义包含一些技术细节,以避免无用的选择

    memberd(X, [E|Es]) :-
       if_(X = E, true, memberd(X, Es)).
    
    使用
    库(reif)
    对于 和 这扩展到:

    memberd(X, [E|Es]) :-
        (   X\=E
        ->  memberd(X, Es)
        ;   X==E
        ->  true
        ;   X=E,
            true
        ;   dif(X, E),
            memberd(X, Es)
        ).
    

    这是第二个问题的另一个答案

  • 立即返回的member/2的代码是什么
  • 如果您只想检查
    X
    是否是
    Es
    的成员,并且两者都是地线,则可以使用

    memberchk(X, Es).
    
    memberchk/2
    是一个,但如果不是,则可以将其定义为

    memberchk(X, Es) :-
        member(X, Es),
        !.
    
    成员/2
    调用后的剪切(
    )会告诉Prolog忘记调用可能仍然需要尝试的任何其他选择

    您的示例决定性地(立即)成功:

    但是请注意,
    memberchk/2
    member/2
    有很大不同。例如:

    ?- findall(X, member(X, [1, 2, 3]), Xs).
    Xs = [1, 2, 3].
    
    ?- findall(X, memberchk(X, [1, 2, 3]), Xs).
    Xs = [1].
    

    没错,我要的是荣誉。
    ?- findall(X, member(X, [1, 2, 3]), Xs).
    Xs = [1, 2, 3].
    
    ?- findall(X, memberchk(X, [1, 2, 3]), Xs).
    Xs = [1].