Prolog断言/ 1对它传递的术语有什么作用?

问题描述 投票:2回答:3

我试图理解断言和撤回对它们传递的术语的作用。如果我运行以下内容:

?- assertz(item(first)).
true.

?- assertz(item(second)).
true.

?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.

?- retract(item(X)).
X = first ;
X = second ;
false.

retract / 1删除了所有项目,但我的writeln / 1从未被调用,因此它显示retract实际上并不解析它传递的术语。看起来它正在做一些特殊操作:

  • 在数据库中仅使用事实(即没有尾部的规则)统一该术语
  • 在应用统一替换后撤回每一个

这是正确的吗?或者是其他事情发生在这里?

换句话说:如果我编写自己的单个参数规则,Prolog不会自动将项目(X)与数据库统一,并遍历所有第1项的事实。它只给我项目(X)。如何缩回它的魔力?

?- assertz((myRule(X) :- writeln(X))).
true.

? myRule(item(X)).
item(_2556)
true.

回答进一步澄清:根据User9213的回答,似乎答案是“撤回(但不断言!)有一个有趣的行为,它在对数据库执行某些操作之前对其术语进行简单统一”。我想知道为什么我见过的其他内置函数(如atom / 1和writeln / 1)似乎没有这样做。也许它比我经历的更常见?

为了保持一致性,似乎retract应该有必要的基础术语,如果用户想要做我上面的例子,他们可以做到这一点:

? - (项目(X),撤回(项目(X)))。

这一切都让我觉得我错过了一些东西,或者这些内置功能只是设计不一致?任何可以解释这一点的澄清都会很棒。

prolog
3个回答
2
投票

为了将我的声音添加到合唱中,是的,所有这些谓词(assert*retract*)操纵Prolog数据库中的事实和规则;他们不会将他们的论点评估为事实或规则。是的,他们只是在他们的论点与数据库中的事实和规则之间进行“句法”统一。

Prolog是一个homoiconic language。该程序可以像操作数据一样进行操作;数据结构可以解释为它们是程序。最重要的是:某个结构是数据还是程序,仅取决于上下文。

你似乎明白了这一点,但对于下一个可怜的灵魂来说,你的问题和这个答案是偶然的,这里有一个玩具示例来展示。

有一个built-in predicate atom/1成功,如果它的论证是,原子:

?- atom(foo).
true.

?- atom(Bar). % Bar is a free variable, which is not an atom
false.

?- atom(atom(bar)). % atom(bar) is a compound term, which is not an atom
false.

atom(bar)只是最后一个查询中的复合词。它是一个带有仿函数原子/ 1的复合词。它唯一的论点是原子。所以,如果您现在查询它:

?- atom(bar).
true.

还有这个非常好的谓词called call。它使模糊程序和数据之间的界限变得更加容易。以下三个查询的含义相同:

?- atom(bar).
true.

?- call(atom, bar).
true.

?- call(atom(bar)).
true.

此外,您可以动态(在运行时)创建数据结构并将其评估为程序。这是一个简单的call/2实现,可以评估谓词,提供谓词名称和参数列表。它constructs the compound term using "univ"并通过将它放在一个子区域应该是的插槽中来评估它。我将其命名为my_call/2,我将使用assertz将其添加到数据库中:

?- assertz((my_call(Name, Args) :- Goal =.. [Name|Args], Goal)).
true.

?- my_call(between, [1, 3, X]).
X = 1 ;
X = 2 ;
X = 3.

你看到发生了什么事吗? (注意:似乎call是Prolog的一个相对较新的补充。在call被广泛使用之前,你必须做这个技巧,如果你想元调用谓词。我不知道这是从经验,只是基于的教育猜测我读过或听过的东西,现在不能引用它们。)


所以,让我们再试一次。实际上事情更复杂,但非常简单:

Prolog程序是一组谓词。没有订购!

每个谓词都是一个子句列表。它是一个列表,因为谓词可能有0个或更多个子句,并且它们有顺序。

条款可以是事实或规则。

规则是带有仿函数:-/2的复合词。是的,这是对的。看看我的意思:

?- assertz(:-(foo(X), between(1, 3, X))).
true.

?- listing(foo/1).
:- dynamic foo/1.

foo(A) :-
    between(1, 3, A).

true.

这只是写它的另一种方式。它更传统。

确实,这两者非常不同:

foo(X). % a fact
foo(X) :- between(1, 3, X). % a rule

你无法将这一个与另一个统一起来。这就是为什么,如果你想收回foo(X) :- between(1, 3, X),你不能只通过foo(X)作为撤回的参数。或者,要完成您的示例:

?- assertz(item(first)).
true.

?- assertz(item(second)).
true.

?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.

?- retract(item(X)).
X = first ;
X = second ;
false.

?- retract((item(X) :- X = Y, writeln(X))).
Y = third.

你现在看到了吗?


2
投票

我有一个模糊的记忆,有一个retractall/1retract/1并存,事实证明它是这样的情况。 retract/1接受Prolog术语,正如文档所述:

缩回(+期限)

当Term是一个原子或一个术语时,它与数据库中的第一个统一事实或子句统一起来。事实或子句将从数据库中删除。

强调我加入了。这由以下说明:

?- asserta(foo(X) :- X = 2 ; X = 4).
true.

?- foo(X).
X = 2 ;
X = 4.

?- retract(foo(X)).
false.

?- foo(X).
X = 2 ;
X = 4.

?- retract(foo(X) :- X = 2 ; X = 4).
true.

?- foo(X).
false.

请注意,如果您提供给asserta/1的完整条款,它将被撤回。正如@CapelliC在下面指出的那样,你也可以提供一个带有变量的子句作为参数来用物体收回东西:

retract(foo(X) :- Y).

但是,如果您确实要撤消与模式匹配的内容,可以使用retractall/1,文档说明:

retractall(+头)

数据库中与Head统一的所有事实或条款都将被删除。

这由以下说明:

?- asserta(foo(X) :- X = 2 ; X = 4).
true.

?- foo(X).
X = 2 ;
X = 4.

?- retractall(foo(X)).
true.

?- foo(X).
false.

这两者之间的另一个重要区别是,retract/1将一次删除一件事,它将统一这些事情:

?- asserta(foo(X) :- X = 2).
true.

?- asserta(foo(X) :- X = 4).
true.

?- retract(foo(X) :- Y).
Y =  (X=4) ;
Y =  (X=2) .

这与retractall/1相反,?- asserta(foo(X) :- X=2). true. ?- asserta(foo(X) :- X=4). true. ?- foo(X). X = 4 ; X = 2. ?- retractall(foo(X)). true. ?- foo(X). false. 将删除与模式匹配的所有内容,而不会统一任何内容:

retract/1

因此,retractall/1实际上是为了做一次一次的撤消,但期望形状像你断言的那样,而definition of assert in swi-prolog只想要一个头,把它当作一个模式,并将删除尽可能多的东西匹配模式。

这无疑帮助我提高了对Prolog的理解,所以我希望它对你有所帮助!


1
投票

qazxswpoi是:

将子句(事实或规则)置入数据库。谓词asserta / 1将该子句断言为谓词的第一个子句,而assertz / 1将该子句断言为最后一个子句。不推荐使用的断言/ 1等同于assertz / 1。如果目标模块的程序空间有限(请参阅set_module / 1),则asserta / 1可以引发resource_error(program_space)异常。下面的示例添加了两个事实和规则。请注意规则周围的双括号。

因此,它不会打电话或推断任何东西!这只是对事实和主动记忆规则的断言。

© www.soinside.com 2019 - 2024. All rights reserved.