Prolog与列表统一

Prolog与列表统一,prolog,unification,prolog-anonymous-variable,Prolog,Unification,Prolog Anonymous Variable,我试图进一步理解Prolog,以及它如何处理统一。在本例中,它如何处理与列表的统一 这是我的知识库 member(X, [X|_]). member(X, [_|T]):- member(X, T). 如果我正确理解了这个过程。如果成员(X[X | |)不为真,则它将进入递归规则,如果X在列表T中,则[|T]与T统一 那么递归谓词中的匿名变量会发生什么变化呢?它会被丢弃吗?我很难理解列表的确切统一过程,因为[\u124; T]是两个变量,而不是一个。我只是想弄清楚统一过程是如何精确地处理列表的

我试图进一步理解Prolog,以及它如何处理统一。在本例中,它如何处理与列表的统一

这是我的知识库

member(X, [X|_]).
member(X, [_|T]):- member(X, T).
如果我正确理解了这个过程。如果
成员(X[X | |)
不为真,则它将进入递归规则,如果
X
在列表
T
中,则
[|T]
T
统一


那么递归谓词中的匿名变量会发生什么变化呢?它会被丢弃吗?我很难理解列表的确切统一过程,因为
[\u124; T]
是两个变量,而不是一个。我只是想弄清楚统一过程是如何精确地处理列表的。

列表只是一个带有
的复合词。
函子:

1 ?- [_|T] = .(_,T).
true.

2 ?- [_|T] =.. X.
X = ['.', _G2393, T].
复合术语结构统一的一般过程适用于:

3 ?- [A|T] = .(B,R). 
A = B,
T = R.
[A | T]
实际上是
(A,T)
,因此函子(
)和算术(两个术语都是二进制的,属于算术2)匹配,因此相应的成分也匹配

是的,出于报告统一结果的目的,将忽略匿名变量
\uu
。否则,它只是一个新的唯一命名变量

它进入递归规则,如果X在列表T中,则[|T]与T统一

不完全是。作为从句选择的一部分,统一发生在“继续”之前。将列表
L
[|T]
统一,就是选择它的“尾部”,并让
T
引用它。例如

4 ?- L = [1,2,3], L = [_|T].
L = [1, 2, 3],
T = [2, 3].

1
但未报告)。

假设
Y

member(X, [Y|T]):- member(X, T).
那么这是
True
不管
Y
。现在您正在“返回”
成员(X,T)
。换句话说,您正在丢弃
Y
并“返回”
成员(X,T)。

\u
意味着,不管它是什么,忽略该变量

_u与任何其他变量一样,只是您看到的每个变量都是 作为不同的变量处理,Prolog不会向您显示它是什么 与…相结合。那里没有什么特别的行为;如果你不明白的话 关于行为,只要发明一个全新的变量并将其 在那里看看它能做什么


在本例中,函数检查列表中是否存在给定元素,因此,取列表的第一个元素,检查是否相等,如果不相等,则丢弃该元素并继续。a | B表示一个列表,其中a是头元素,B是整个剩余列表

因此,简单地解释一下算法:

  • 子句:如果X是列表的第一个元素,则谓词成功
  • 如果不是这样,我们试着在列表的末尾找到X。因此,我们递归地调用member,但是我们现在传递的不是整个列表,而是除了head元素之外的列表。换句话说,我们一步一步地浏览列表,始终首先查看head元素。如果这不是我们的元素,我们会进一步挖掘

  • 将匿名变量
    \uu
    视为以后不需要的变量。如果你用大写字母替换
    ,算法也会起作用,但是它会给你一个警告,你命名了一个从未使用过的变量。

    我认为你的主要问题列表如何表示为变量已经得到了充分的回答,但我觉得序言还有一些其他方面需要澄清

    要理解Prolog谓词和子句,最好不要将它们视为“返回”事物的“函数”,即使是隐喻。它可以引导你走上序言中命令式思维的黑暗道路

    在考虑谓词时:

    (1) member(X, [X|_]).
    (2) member(X, [_|T]) :- member(X, T).
    
    member/2
    视为描述元素
    X
    何时为列表
    L
    成员的关系,子句是确定其何时为真的规则

    我假设您已经知道如何根据其他答案(例如Will Ness的详细答案)在Prolog中表示列表

    第一条规定:

    (1)
    X
    [X|||]
    的成员,无论列表的尾部是什么
    [X|||]

    在该表示法中,变量
    表示列表的尾部
    [X |]
    X
    表示该列表的第一个元素。
    X
    是这个列表中的一员,这一点非常正确,因此
    member(X[X |))是一个事实。不管列表的尾部是什么,这都是正确的,因此我们只使用
    (一个匿名变量),因为此规则不需要这些信息。从技术上讲,Prolog不会“扔掉值”,但程序员会扔掉它,因为程序员没有使用它。如果我们改为说,
    member(X,[X | T])。
    这会很好,但我们没有使用
    T
    。Prolog可能会实例化它,但不会使用它。这就像在C中赋值
    x=3
    ,但不使用它的值。在这种情况下,Prolog将指示关于“singleton”变量的警告。注意这些,因为这通常意味着你拼错了什么或忘记了什么

    下一个规则是递归的。它说:

    (2) 如果
    X
    是该列表尾部(
    T
    )的成员,则无论列表的第一个元素是什么,
    X
    都是列表的成员

    这里我们考虑的是一个不那么简单的情况,列表中的第一个元素可能与
    X
    不匹配,因此
    member(X,L)
    的真值在此规则中取决于
    member(X,T)
    的真值,其中
    T
    L
    的尾部(除第一个元素外的所有元素)。规则不会将
    成员(X,T)与
    成员(X,T)
    统一起来,因此它不会像您所说的那样将
    T
    成员(X,T)
    统一起来
    member(b, [a,b,c]).
    
    member(X, [X|_]).
    
    member(X, [_|T]) :- member(X, T).
    
    member(b, [_|[b,c]]) :- member(b, [b,c]).
    
    | ?- member(b, [a,b,c]).
    
    true ? ;
    
    no
    | ?-
    
    member(E, [a,b,c]).
    
    | ?- member(E, [a,b,c]).
    
    E = a ?
    
    | ?- member(E, [a,b,c]).
    
    E = a ? ;
    
    E = b ?