在给定一组程序规则的情况下,匿名变量在Prolog查询的解析中扮演什么角色,这是一个快速而简单的问题。因此,我理解SLD解析的最简单形式是如何工作的,SLD树是通过从一组目标项中提取一些项(基于选择规则,例如FIRST(并遍历所有程序规则来构建的,以查看哪条规则的左手边(可以说是结果(可以与手头的项相统一。统一两个给定项的方法是取一个由两个项组成的差集,看看变量是否可以代替项,从而使差消失,你可以通过依次取最左边的单个差,并检查在构成差的两个集合中,一个是不出现在另一个中的变量,并用一个将变量映射到项上的变量组成当前替换(从空替换或身份替换开始(。
现在,当匿名变量(_(发挥作用时,我怀疑正确有效地做到这一点的诀窍在于改变确定两个项之间最左边差异的方式,只要其中一个项是匿名变量,就忽略一对项。显然正确的方法是将目标和程序集中的_的每个实例重命名为一个新的变量名,并使用它们进行求解。
它实际上是如何完成的?我的想法足够吗?或者还有更多的想法吗?(此外,如果我理解SLD解析的工作方式中缺少一些东西,我将不胜感激,除了否定、调用、封顶、算术谓词和更复杂的东西。(
Prolog匿名变量在SLD解析或术语统一中不起作用,但在Prolog代码和Prolog查询中起着实际作用。匿名变量的一个基本方面是,每次出现匿名变量都是不同的变量。考虑以下查询:
| ?- a(_, _) = a(1, 2).
yes
如果两个匿名变量是同一个变量,那么统一就会失败。现在考虑查询:
| ?- a(X, _) = a(1, 2).
X = 1
yes
仅为非匿名变量的变量报告变量绑定。这允许每当我们对变量的任何绑定不感兴趣时使用匿名变量。
匿名变量还简化了谓词定义的编写,它们类似于"不在乎"变量。以member/2
谓词的常见定义为例:
member(Element, [Element| _]).
member(Element, [_| List]) :-
member(Element, List).
在第一个子句中,我们不关心列表尾部。在第二个子句中,我们不关心列表标题。通过使用匿名变量,我们可以忽略这些子项,避免编译器抱怨在子句中使用一次的变量。
更新
请注意,查询中的所有不同变量都有唯一的内部变量引用,不要与用户键入的变量名混淆。变量名称仅由顶级解释器用于报告成功查询的绑定。用于证明查询的推理机制使用变量(内部(引用。以下查询,使用ISO Prolog标准read_term/2
谓词和标准选项可能会有所帮助:
| ?- read_term(Term, [variable_names(Names), variables(Variables)]).
a(X, _, Y, _).
Names = ['X'=A,'Y'=B]
Term = a(A,C,B,D)
Variables = [A,C,B,D]
yes
在术语read中,有四个不同的变量,但其中只有两个具有(用户提供的(名称。
这是答案中的注释,因为注释无法根据需要格式化它。
使用SWI Prolog
?- trace,(_=_).
Call: (11) _1834=_1836 ? creep
Exit: (11) _1834=_1834 ? creep
true.
每个匿名变量都被创建为一个单独的变量。当统一发生时,一个变量与另一个变量统一。